capnproto-c++-1.1.0/0000755000175000017500000000000014731562205014747 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/pkgconfig/0000755000175000017500000000000014731562205016716 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/pkgconfig/capnpc.pc.in0000644000175000017500000000057114527152321021113 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Cap'n Proto Description: Insanely fast serialization system compiler library Version: @VERSION@ Libs: -L${libdir} -lcapnpc @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Libs.private: @LIBS@ Requires: kj = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/kj.pc.in0000644000175000017500000000047414527152321020255 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ Framework Library Description: Basic utility library called KJ Version: @VERSION@ Libs: -L${libdir} -lkj @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/capnp.pc.in0000644000175000017500000000054714527152321020753 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Cap'n Proto Description: Insanely fast serialization system Version: @VERSION@ Libs: -L${libdir} -lcapnp @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Libs.private: @LIBS@ Requires: kj = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/kj-http.pc.in0000644000175000017500000000054714527152321021233 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ HTTP Library Description: Basic utility library called KJ (HTTP part) Version: @VERSION@ Libs: -L${libdir} -lkj-http @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Requires: kj-async = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/capnp-rpc.pc.in0000644000175000017500000000042014527152321021523 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Cap'n Proto RPC Description: Fast object-oriented RPC system Version: @VERSION@ Libs: -L${libdir} -lcapnp-rpc Requires: capnp = @VERSION@ kj-async = @VERSION@ Cflags: -I${includedir} capnproto-c++-1.1.0/pkgconfig/capnp-websocket.pc.in0000644000175000017500000000054114527152321022731 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Cap'n Proto WebSocket RPC Description: WebSocket MessageStream for Cap'n Proto Version: @VERSION@ Libs: -L${libdir} -lcapnp-websocket Requires: capnp = @VERSION@ capnp-rpc = @VERSION@ kj = @VERSION@ kj-async = @VERSION@ kj-http = @VERSION@ Cflags: -I${includedir} capnproto-c++-1.1.0/pkgconfig/capnp-json.pc.in0000644000175000017500000000043514527152321021716 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Cap'n Proto JSON Description: JSON encoder and decoder for Cap'n Proto objects Version: @VERSION@ Libs: -L${libdir} -lcapnp-json Requires: capnp = @VERSION@ kj = @VERSION@ Cflags: -I${includedir} capnproto-c++-1.1.0/pkgconfig/kj-test.pc.in0000644000175000017500000000054314527152321021227 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ Test Framework Description: Basic utility library called KJ (test part) Version: @VERSION@ Libs: -L${libdir} -lkj-test @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Requires: kj = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/kj-tls.pc.in0000644000175000017500000000054514527152321021054 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ TLS Adapters Description: Basic utility library called KJ (TLS part) Version: @VERSION@ Libs: -L${libdir} -lkj-tls @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Requires: kj-async = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/kj-gzip.pc.in0000644000175000017500000000055014527152321021217 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ Gzip Adapters Description: Basic utility library called KJ (gzip part) Version: @VERSION@ Libs: -L${libdir} -lkj-gzip @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Requires: kj-async = @VERSION@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/pkgconfig/kj-async.pc.in0000644000175000017500000000061014527152321021360 0ustar00kentonkenton00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: KJ Async Framework Library Description: Basic utility library called KJ (async part) Version: @VERSION@ Libs: -L${libdir} -lkj-async @ASYNC_LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @STDLIB_FLAG@ Requires: kj = @VERSION@ Cflags: -I${includedir} @ASYNC_LIBS@ @PTHREAD_CFLAGS@ @STDLIB_FLAG@ @CAPNP_LITE_FLAG@ capnproto-c++-1.1.0/aclocal.m40000644000175000017500000012305314731562164016617 0ustar00kentonkenton00000000000000# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, [m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/acx_pthread.m4]) m4_include([m4/ax_cxx_compile_stdcxx_14.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) capnproto-c++-1.1.0/CMakeLists.txt0000644000175000017500000002111514731562162017511 0ustar00kentonkenton00000000000000cmake_minimum_required(VERSION 3.6) project("Cap'n Proto" CXX) set(VERSION 1.1.0) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(CTest) include(CheckIncludeFileCXX) include(GNUInstallDirs) if(MSVC) check_include_file_cxx(initializer_list HAS_CXX14) else() check_include_file_cxx(initializer_list HAS_CXX14 "-std=gnu++1y") endif() if(NOT HAS_CXX14) message(SEND_ERROR "Requires a C++14 compiler and standard library.") endif() # these arguments are passed to all install(TARGETS) calls set(INSTALL_TARGETS_DEFAULT_ARGS EXPORT CapnProtoTargets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) # Options ====================================================================== option(EXTERNAL_CAPNP "Use the system capnp binary, or the one specified in $CAPNP, instead of using the compiled one." OFF) option(CAPNP_LITE "Compile Cap'n Proto in 'lite mode', in which all reflection APIs (schema.h, dynamic.h, etc.) are not included. Produces a smaller library at the cost of features. All programs built against the library must be compiled with -DCAPNP_LITE. Requires EXTERNAL_CAPNP." OFF) # Check for invalid combinations of build options if(CAPNP_LITE AND BUILD_TESTING AND NOT EXTERNAL_CAPNP) message(SEND_ERROR "You must set EXTERNAL_CAPNP when using CAPNP_LITE and BUILD_TESTING.") endif() if(CAPNP_LITE) set(CAPNP_LITE_FLAG "-DCAPNP_LITE") # This flag is attached as PUBLIC target_compile_definition to kj target else() set(CAPNP_LITE_FLAG) endif() set(WITH_OPENSSL "AUTO" CACHE STRING "Whether or not to build libkj-tls by linking against openssl") # define list of values GUI will offer for the variable set_property(CACHE WITH_OPENSSL PROPERTY STRINGS AUTO ON OFF) set(WITH_ZLIB "AUTO" CACHE STRING "Whether or not to build libkj-gzip by linking against zlib") set_property(CACHE WITH_ZLIB PROPERTY STRINGS AUTO ON OFF) # shadow cache variable original value with ON/OFF, # so from now on OpenSSL-specific code just has to check: # if (WITH_OPENSSL) # ... # endif() if (CAPNP_LITE) set(WITH_OPENSSL OFF) elseif (WITH_OPENSSL STREQUAL "AUTO") find_package(OpenSSL COMPONENTS Crypto SSL) if (OPENSSL_FOUND) set(WITH_OPENSSL ON) else() set(WITH_OPENSSL OFF) endif() elseif (WITH_OPENSSL) find_package(OpenSSL REQUIRED COMPONENTS Crypto SSL) endif() # shadow cache variable original value with ON/OFF, # so from now on ZLIB-specific code just has to check: # if (WITH_ZLIB) # ... # endif() if(CAPNP_LITE) set(WITH_ZLIB OFF) elseif (WITH_ZLIB STREQUAL "AUTO") find_package(ZLIB) if(ZLIB_FOUND) set(WITH_ZLIB ON) else() set(WITH_ZLIB OFF) endif() elseif (WITH_ZLIB) find_package(ZLIB REQUIRED) endif() set(WITH_FIBERS "AUTO" CACHE STRING "Whether or not to build libkj-async with fibers") # define list of values GUI will offer for the variable set_property(CACHE WITH_FIBERS PROPERTY STRINGS AUTO ON OFF) # CapnProtoConfig.cmake.in needs this variable. set(_WITH_LIBUCONTEXT OFF) if (WITH_FIBERS OR WITH_FIBERS STREQUAL "AUTO") set(_capnp_fibers_found OFF) if (WIN32 OR CYGWIN) set(_capnp_fibers_found ON) else() # Fibers need makecontext, setcontext, getcontext, swapcontext that may be in libc, # or in libucontext (e.g. for musl). # We assume that makecontext implies that the others are present. include(CheckLibraryExists) check_library_exists(c makecontext "" HAVE_UCONTEXT_LIBC) if (HAVE_UCONTEXT_LIBC) set(_capnp_fibers_found ON) else() # Try with libucontext find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(libucontext IMPORTED_TARGET libucontext) if (libucontext_FOUND) set(_WITH_LIBUCONTEXT ON) set(_capnp_fibers_found ON) endif() else() set(_capnp_fibers_found OFF) endif() endif() endif() if (_capnp_fibers_found) set(WITH_FIBERS ON) elseif(WITH_FIBERS STREQUAL "AUTO") set(WITH_FIBERS OFF) else() message(FATAL_ERROR "Missing 'makecontext', 'getcontext', 'setcontext' or 'swapcontext' symbol in libc and no libucontext found: KJ won't be able to build with fibers. Disable fibers (-DWITH_FIBERS=OFF).") endif() endif() if(MSVC) # TODO(cleanup): Enable higher warning level in MSVC, but make sure to test # build with that warning level and clean out false positives. add_compile_options(/wo4503) # Only warn once on truncated decorated names. The maximum symbol length MSVC # supports is 4k characters, which the parser framework regularly blows. The # compiler likes to print out the entire type that went over the limit along # with this warning, which gets unbearably spammy. That said, we don't want to # just ignore it, so I'm letting it trigger once until we find some places to # inject ParserRefs. else() # Note that it's important to add new CXXFLAGS before ones specified by the # user, so that the user's flags override them. This is particularly # important if -Werror was enabled and then certain warnings need to be # disabled, as is done in super-test.sh. # # We enable a lot of warnings, but then disable some: # * strict-aliasing: We use type-punning in known-safe ways that GCC doesn't # recognize as safe. # * sign-compare: Low S/N ratio. # * unused-parameter: Low S/N ratio. add_compile_options(-Wall -Wextra -Wno-strict-aliasing -Wno-sign-compare -Wno-unused-parameter) if(DEFINED CMAKE_CXX_EXTENSIONS AND NOT CMAKE_CXX_EXTENSIONS) message(SEND_ERROR "Cap'n Proto requires compiler-specific extensions (e.g., -std=gnu++14). Please leave CMAKE_CXX_EXTENSIONS undefined or ON.") endif() if (NOT ANDROID) add_compile_options(-pthread) endif() endif() # Source ======================================================================= include(CapnProtoMacros) add_subdirectory(src) # Install ====================================================================== include(CMakePackageConfigHelpers) # We used to use write_basic_package_version_file(), but since the autotools build needs to install # a config version script as well, I copied the AnyNewerVersion template from my CMake Modules # directory to Cap'n Proto's cmake/ directory (alternatively, we could make the autotools build # depend on CMake). # # We might as well use the local copy of the template. In the future we can modify the project's # version compatibility policy just by changing that file. set(PACKAGE_VERSION ${VERSION}) configure_file(cmake/CapnProtoConfigVersion.cmake.in cmake/CapnProtoConfigVersion.cmake @ONLY) set(CONFIG_PACKAGE_LOCATION ${CMAKE_INSTALL_LIBDIR}/cmake/CapnProto) configure_package_config_file(cmake/CapnProtoConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/CapnProtoConfig.cmake INSTALL_DESTINATION ${CONFIG_PACKAGE_LOCATION} PATH_VARS CMAKE_INSTALL_FULL_INCLUDEDIR ) export(EXPORT CapnProtoTargets FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/CapnProtoTargets.cmake" NAMESPACE CapnProto:: ) install(EXPORT CapnProtoTargets FILE CapnProtoTargets.cmake NAMESPACE CapnProto:: DESTINATION ${CONFIG_PACKAGE_LOCATION} ) install(FILES cmake/CapnProtoMacros.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake/CapnProtoConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake/CapnProtoConfigVersion.cmake DESTINATION ${CONFIG_PACKAGE_LOCATION} ) #install CapnProtoMacros for CapnProtoConfig.cmake build directory consumers configure_file(cmake/CapnProtoMacros.cmake cmake/CapnProtoMacros.cmake COPYONLY) if(NOT MSVC) # Don't install pkg-config files when building with MSVC # Variables for pkg-config files set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "") # not needed since we use absolute paths in libdir and includedir set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") set(PTHREAD_CFLAGS "-pthread") set(STDLIB_FLAG) # TODO: Unsupported set(CAPNP_PKG_CONFIG_FILES pkgconfig/kj.pc pkgconfig/capnp.pc pkgconfig/capnpc.pc ) if(NOT CAPNP_LITE) list(APPEND CAPNP_PKG_CONFIG_FILES pkgconfig/kj-async.pc pkgconfig/kj-gzip.pc pkgconfig/kj-http.pc pkgconfig/kj-test.pc pkgconfig/kj-tls.pc pkgconfig/capnp-rpc.pc pkgconfig/capnp-websocket.pc pkgconfig/capnp-json.pc ) endif() foreach(pcfile ${CAPNP_PKG_CONFIG_FILES}) configure_file(${pcfile}.in "${CMAKE_CURRENT_BINARY_DIR}/${pcfile}" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${pcfile}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endforeach() unset(STDLIB_FLAG) unset(PTHREAD_CFLAGS) unset(includedir) unset(libdir) unset(exec_prefix) unset(prefix) endif() capnproto-c++-1.1.0/cmake/0000755000175000017500000000000014731562205016027 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/cmake/CapnProtoConfigVersion.cmake.in0000644000175000017500000000313014527152321024031 0ustar00kentonkenton00000000000000# This is a copy of /usr/share/cmake-3.5/Modules/BasicConfigVersion-AnyNewerVersion.cmake.in, with # the following change: # - @CVF_VERSION renamed to @PACKAGE_VERSION@. Autoconf defines a PACKAGE_VERSION # output variable for us, so might as well take advantage of that. # This is a basic version file for the Config-mode of find_package(). # It is used by write_basic_package_version_file() as input file for configure_file() # to create a version-file which can be installed along a config.cmake file. # # The created file sets PACKAGE_VERSION_EXACT if the current version string and # the requested version string are exactly the same and it sets # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version. # The variable PACKAGE_VERSION must be set before calling configure_file(). set(PACKAGE_VERSION "@PACKAGE_VERSION@") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") return() endif() # check that the installed version has the same 32/64bit-ness as the one which is currently searching: if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@") math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() capnproto-c++-1.1.0/cmake/CapnProtoTargets.cmake0000644000175000017500000002216014527152321022266 0ustar00kentonkenton00000000000000# This CMake script adds imported targets for each shared library and executable distributed by # Cap'n Proto's autotools build. # # This file IS NOT USED by the CMake build! The CMake build generates its own version of this script # from its set of exported targets. I used such a generated script as a reference when writing this # one. # # The set of library targets provided by this script is automatically generated from the list of .pc # files maintained in configure.ac. The set of executable targets is hard-coded in this file. # # You can request that this script print debugging information by invoking cmake with: # # -DCapnProto_DEBUG=ON # # TODO(someday): Distinguish between debug and release builds. I.e., set IMPORTED_LOCATION_RELEASE # rather than IMPORTED_LOCATION, etc., if this installation was configured as a release build. But # how do we tell? grep for -g in CXXFLAGS? if(CMAKE_VERSION VERSION_LESS 3.1) message(FATAL_ERROR "CMake >= 3.1 required") endif() set(forwarded_config_flags) if(CapnProto_FIND_QUIETLY) list(APPEND forwarded_config_flags QUIET) endif() if(CapnProto_FIND_REQUIRED) list(APPEND forwarded_config_flags REQUIRED) endif() # If the consuming project called find_package(CapnProto) with the QUIET or REQUIRED flags, forward # them to calls to find_package(PkgConfig) and pkg_check_modules(). Note that find_dependency() # would do this for us in the former case, but there is no such forwarding wrapper for # pkg_check_modules(). find_package(PkgConfig ${forwarded_config_flags}) if(NOT ${PkgConfig_FOUND}) # If we're here, the REQUIRED flag must not have been passed, else we would have had a fatal # error. Nevertheless, a diagnostic for this case is probably nice. if(NOT CapnProto_FIND_QUIETLY) message(WARNING "pkg-config cannot be found") endif() set(CapnProto_FOUND OFF) return() endif() function(_capnp_import_pkg_config_target target) # Add an imported library target named CapnProto::${target}, using the output of various # invocations of `pkg-config ${target}`. The generated imported library target tries to mimic the # behavior of a real CMake-generated imported target as closely as possible. # # Usage: _capnp_import_pkg_config_target(target ) set(all_targets ${ARGN}) pkg_check_modules(${target} ${forwarded_config_flags} ${target}) if(NOT ${${target}_FOUND}) if(NOT CapnProto_FIND_QUIETLY) message(WARNING "CapnProtoConfig.cmake was configured to search for ${target}.pc, but pkg-config cannot find it. Ignoring this target.") endif() return() endif() if(CapnProto_DEBUG) # Dump the information pkg-config discovered. foreach(var VERSION LIBRARY_DIRS LIBRARIES LDFLAGS_OTHER INCLUDE_DIRS CFLAGS_OTHER) message(STATUS "${target}_${var} = ${${target}_${var}}") endforeach() endif() if(NOT ${${target}_VERSION} VERSION_EQUAL ${CapnProto_VERSION}) if(NOT CapnProto_FIND_QUIETLY) message(WARNING "CapnProtoConfig.cmake was configured to search for version ${CapnProto_VERSION}, but ${target} version ${${target}_VERSION} was found. Ignoring this target.") endif() return() endif() # Make an educated guess as to what the target's .so and .a filenames must be. set(target_name_shared ${CMAKE_SHARED_LIBRARY_PREFIX}${target}-${CapnProto_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}) set(target_name_static ${CMAKE_STATIC_LIBRARY_PREFIX}${target}${CMAKE_STATIC_LIBRARY_SUFFIX}) # Find the actual target's file. find_library() sets a cache variable, so I made the variable name # unique-ish. find_library(CapnProto_${target}_IMPORTED_LOCATION NAMES ${target_name_shared} ${target_name_static} # prefer libfoo-version.so over libfoo.a PATHS ${${target}_LIBRARY_DIRS} NO_DEFAULT_PATH ) # If the installed version of Cap'n Proto is in a system location, pkg-config will not have filled # in ${target}_LIBRARY_DIRS. To account for this, fall back to a regular search. find_library(CapnProto_${target}_IMPORTED_LOCATION NAMES ${target_name_shared} ${target_name_static} # prefer libfoo-version.so over libfoo.a ) if(NOT CapnProto_${target}_IMPORTED_LOCATION) # Not an error if the library doesn't exist -- we may have found a lite mode installation. if(CapnProto_DEBUG) message(STATUS "${target} library does not exist") endif() return() endif() # Record some information about this target -- shared versus static, location and soname -- which # we'll use to build our imported target later. set(target_location ${CapnProto_${target}_IMPORTED_LOCATION}) get_filename_component(target_name "${target_location}" NAME) set(target_type STATIC) set(imported_soname_property) if(target_name STREQUAL ${target_name_shared}) set(target_type SHARED) set(imported_soname_property IMPORTED_SONAME ${target_name}) endif() # Each library dependency of the target is either the target itself, a sibling Cap'n Proto # library, or a system library. We ignore the first case by removing this target from the # dependencies. The remaining dependencies are either passed through or, if they are a sibling # Cap'n Proto library, prefixed with `CapnProto::`. set(dependencies ${${target}_LIBRARIES}) list(REMOVE_ITEM dependencies ${target}) set(target_interface_libs) foreach(dependency ${dependencies}) list(FIND all_targets ${dependency} target_index) # TODO(cleanup): CMake >= 3.3 lets us write: `if(NOT ${dependency} IN_LIST all_targets)` if(target_index EQUAL -1) list(APPEND target_interface_libs ${dependency}) else() list(APPEND target_interface_libs CapnProto::${dependency}) endif() endforeach() add_library(CapnProto::${target} ${target_type} IMPORTED) set_target_properties(CapnProto::${target} PROPERTIES ${imported_soname_property} IMPORTED_LOCATION "${target_location}" # TODO(cleanup): Use cxx_std_14 once it's safe to require cmake 3.8. INTERFACE_COMPILE_FEATURES "cxx_generic_lambdas" INTERFACE_COMPILE_OPTIONS "${${target}_CFLAGS_OTHER}" INTERFACE_INCLUDE_DIRECTORIES "${${target}_INCLUDE_DIRS}" # I'm dumping LDFLAGS_OTHER in with the libraries because there exists no # INTERFACE_LINK_OPTIONS. See https://gitlab.kitware.com/cmake/cmake/issues/16543. INTERFACE_LINK_LIBRARIES "${target_interface_libs};${${target}_LDFLAGS_OTHER}" ) if(CapnProto_DEBUG) # Dump all the properties we generated for the imported target. foreach(prop IMPORTED_LOCATION IMPORTED_SONAME INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES) get_target_property(value CapnProto::${target} ${prop}) message(STATUS "CapnProto::${target} ${prop} = ${value}") endforeach() endif() endfunction() # ======================================================================================== # Imported library targets # Build a list of targets to search for from the list of .pc files. # I.e. [somewhere/foo.pc, somewhere/bar.pc] -> [foo, bar] set(library_targets) foreach(filename ${CAPNP_PKG_CONFIG_FILES}) get_filename_component(target ${filename} NAME_WE) list(APPEND library_targets ${target}) endforeach() # Try to add an imported library target CapnProto::foo for each foo.pc distributed with Cap'n Proto. foreach(target ${library_targets}) _capnp_import_pkg_config_target(${target} ${library_targets}) endforeach() # Handle lite-mode and no libraries found cases. It is tempting to set a CapnProto_LITE variable # here, but the real CMake-generated implementation does no such thing -- we'd need to set it in # CapnProtoConfig.cmake.in itself. if(TARGET CapnProto::capnp AND TARGET CapnProto::kj) if(NOT TARGET CapnProto::capnp-rpc) if(NOT CapnProto_FIND_QUIETLY) message(STATUS "Found an installation of Cap'n Proto lite. Executable and library targets beyond libkj and libcapnp will be unavailable.") endif() # Lite mode doesn't include the executables, so return here. return() endif() else() # If we didn't even find capnp or kj, then we didn't find anything usable. set(CapnProto_FOUND OFF) return() endif() # ======================================================================================== # Imported executable targets get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) # Add executable targets for the capnp compiler and plugins. This list must be kept manually in sync # with the rest of the project. add_executable(CapnProto::capnp_tool IMPORTED) set_target_properties(CapnProto::capnp_tool PROPERTIES IMPORTED_LOCATION "${_IMPORT_PREFIX}/bin/capnp${CMAKE_EXECUTABLE_SUFFIX}" ) add_executable(CapnProto::capnpc_cpp IMPORTED) set_target_properties(CapnProto::capnpc_cpp PROPERTIES IMPORTED_LOCATION "${_IMPORT_PREFIX}/bin/capnpc-c++${CMAKE_EXECUTABLE_SUFFIX}" ) add_executable(CapnProto::capnpc_capnp IMPORTED) set_target_properties(CapnProto::capnpc_capnp PROPERTIES IMPORTED_LOCATION "${_IMPORT_PREFIX}/bin/capnpc-capnp${CMAKE_EXECUTABLE_SUFFIX}" ) capnproto-c++-1.1.0/cmake/CapnProtoConfig.cmake.in0000644000175000017500000001124114527152321022465 0ustar00kentonkenton00000000000000# Cap'n Proto CMake Package Configuration # # When configured and installed, this file enables client projects to find Cap'n Proto using # CMake's find_package() command. It adds imported targets in the CapnProto:: namespace, such as # CapnProto::kj, CapnProto::capnp, etc. (one target for each file in pkgconfig/*.pc.in), defines # the capnp_generate_cpp() function, and exposes some variables for compatibility with the original # FindCapnProto.cmake module. # # Example usage: # find_package(CapnProto) # capnp_generate_cpp(CAPNP_SRCS CAPNP_HDRS schema.capnp) # add_executable(foo main.cpp ${CAPNP_SRCS}) # target_link_libraries(foo PRIVATE CapnProto::capnp) # target_include_directories(foo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # # If you are using RPC features, use 'CapnProto::capnp-rpc' in the target_link_libraries() call. # # Paths to `capnp` and `capnpc-c++` are exposed in the following variables: # CAPNP_EXECUTABLE # Path to the `capnp` tool (can be set to override). # CAPNPC_CXX_EXECUTABLE # Path to the `capnpc-c++` tool (can be set to override). # # For FindCapnProto.cmake compatibility, the following variables are also provided. Please prefer # using the imported targets in new CMake code. # CAPNP_INCLUDE_DIRS # Include directories for the library's headers. # CANP_LIBRARIES # The Cap'n Proto library paths. # CAPNP_LIBRARIES_LITE # Paths to only the 'lite' libraries. # CAPNP_DEFINITIONS # Compiler definitions required for building with the library. # CAPNP_FOUND # Set if the libraries have been located (prefer using CapnProto_FOUND in new code). # @PACKAGE_INIT@ set(CapnProto_VERSION @VERSION@) set(CAPNP_EXECUTABLE $ CACHE FILEPATH "Location of capnp executable") set(CAPNPC_CXX_EXECUTABLE $ CACHE FILEPATH "Location of capnpc-c++ executable") set(CAPNP_INCLUDE_DIRECTORY "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@") # work around http://public.kitware.com/Bug/view.php?id=15258 if(NOT _IMPORT_PREFIX) set(_IMPORT_PREFIX ${PACKAGE_PREFIX_DIR}) endif() if (@WITH_OPENSSL@) # WITH_OPENSSL include(CMakeFindDependencyMacro) if (CMAKE_VERSION VERSION_LESS 3.9) # find_dependency() did not support COMPONENTS until CMake 3.9 # # in practice, this call can be erroneous # if the user has only libcrypto installed, but not libssl find_dependency(OpenSSL) else() find_dependency(OpenSSL COMPONENTS Crypto SSL) endif() endif() if (@WITH_ZLIB@) # WITH_ZLIB include(CMakeFindDependencyMacro) find_dependency(ZLIB) endif() if (@_WITH_LIBUCONTEXT@) # _WITH_LIBUCONTEXT set(forwarded_config_flags) if(CapnProto_FIND_QUIETLY) list(APPEND forwarded_config_flags QUIET) endif() if(CapnProto_FIND_REQUIRED) list(APPEND forwarded_config_flags REQUIRED) endif() # If the consuming project called find_package(CapnProto) with the QUIET or REQUIRED flags, forward # them to calls to find_package(PkgConfig) and pkg_check_modules(). Note that find_dependency() # would do this for us in the former case, but there is no such forwarding wrapper for # pkg_check_modules(). find_package(PkgConfig ${forwarded_config_flags}) if(NOT ${PkgConfig_FOUND}) # If we're here, the REQUIRED flag must not have been passed, else we would have had a fatal # error. Nevertheless, a diagnostic for this case is probably nice. if(NOT CapnProto_FIND_QUIETLY) message(WARNING "pkg-config cannot be found") endif() set(CapnProto_FOUND OFF) return() endif() if (CMAKE_VERSION VERSION_LESS 3.6) # CMake >= 3.6 required due to the use of IMPORTED_TARGET message(SEND_ERROR "libucontext support requires CMake >= 3.6.") endif() pkg_check_modules(libucontext IMPORTED_TARGET ${forwarded_config_flags} libucontext) endif() include("${CMAKE_CURRENT_LIST_DIR}/CapnProtoTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/CapnProtoMacros.cmake") # FindCapnProto.cmake provides dependency information via several CAPNP_-prefixed variables. New # code should not rely on these variables, but prefer linking directly to the imported targets we # now provide. However, we should still set these variables to ease the transition for projects # which currently depend on the find-module. set(CAPNP_INCLUDE_DIRS ${CAPNP_INCLUDE_DIRECTORY}) # No need to list all libraries, just the leaves of the dependency tree. set(CAPNP_LIBRARIES_LITE CapnProto::capnp) set(CAPNP_LIBRARIES CapnProto::capnp-rpc CapnProto::capnp-json CapnProto::kj-http) set(CAPNP_DEFINITIONS) if(TARGET CapnProto::capnp AND NOT TARGET CapnProto::capnp-rpc) set(CAPNP_DEFINITIONS -DCAPNP_LITE) endif() set(CAPNP_FOUND ${CapnProto_FOUND}) capnproto-c++-1.1.0/cmake/CapnProtoMacros.cmake0000644000175000017500000001200114527152321022072 0ustar00kentonkenton00000000000000# CAPNP_GENERATE_CPP =========================================================== # # Example usage: # find_package(CapnProto) # capnp_generate_cpp(CAPNP_SRCS CAPNP_HDRS schema.capnp) # add_executable(foo main.cpp ${CAPNP_SRCS}) # target_link_libraries(foo PRIVATE CapnProto::capnp-rpc) # target_include_directories(foo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # # If you are not using the RPC features you can use 'CapnProto::capnp' in the # target_link_libraries call # # Configuration variables (optional): # CAPNPC_OUTPUT_DIR # Directory to place compiled schema sources (default: CMAKE_CURRENT_BINARY_DIR). # CAPNPC_IMPORT_DIRS # List of additional include directories for the schema compiler. # (CAPNPC_SRC_PREFIX and CAPNP_INCLUDE_DIRECTORY are always included.) # CAPNPC_SRC_PREFIX # Schema file source prefix (default: CMAKE_CURRENT_SOURCE_DIR). # CAPNPC_FLAGS # Additional flags to pass to the schema compiler. # # TODO: convert to cmake_parse_arguments function(CAPNP_GENERATE_CPP SOURCES HEADERS) if(NOT ARGN) message(SEND_ERROR "CAPNP_GENERATE_CPP() called without any source files.") endif() set(tool_depends ${EMPTY_STRING}) #Use cmake targets available if(TARGET capnp_tool) if(NOT CAPNP_EXECUTABLE) set(CAPNP_EXECUTABLE $) endif() if(NOT CAPNPC_CXX_EXECUTABLE) get_target_property(CAPNPC_CXX_EXECUTABLE capnpc_cpp CAPNPC_CXX_EXECUTABLE) endif() if(NOT CAPNP_INCLUDE_DIRECTORY) get_target_property(CAPNP_INCLUDE_DIRECTORY capnp_tool CAPNP_INCLUDE_DIRECTORY) endif() list(APPEND tool_depends capnp_tool capnpc_cpp) endif() if(NOT CAPNP_EXECUTABLE) message(SEND_ERROR "Could not locate capnp executable (CAPNP_EXECUTABLE).") endif() if(NOT CAPNPC_CXX_EXECUTABLE) message(SEND_ERROR "Could not locate capnpc-c++ executable (CAPNPC_CXX_EXECUTABLE).") endif() if(NOT CAPNP_INCLUDE_DIRECTORY) message(SEND_ERROR "Could not locate capnp header files (CAPNP_INCLUDE_DIRECTORY).") endif() if(DEFINED CAPNPC_OUTPUT_DIR) # Prepend a ':' to get the format for the '-o' flag right set(output_dir ":${CAPNPC_OUTPUT_DIR}") else() set(output_dir ":.") endif() if(NOT DEFINED CAPNPC_SRC_PREFIX) set(CAPNPC_SRC_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}") endif() get_filename_component(CAPNPC_SRC_PREFIX "${CAPNPC_SRC_PREFIX}" ABSOLUTE) # Default compiler includes. Note that in capnp's own test usage of capnp_generate_cpp(), these # two variables will end up evaluating to the same directory. However, it's difficult to # deduplicate them because if CAPNP_INCLUDE_DIRECTORY came from the capnp_tool target property, # then it must be a generator expression in order to handle usages in both the build tree and the # install tree. This vastly overcomplicates duplication detection, so the duplication doesn't seem # worth fixing. set(include_path -I "${CAPNPC_SRC_PREFIX}" -I "${CAPNP_INCLUDE_DIRECTORY}") if(DEFINED CAPNPC_IMPORT_DIRS) # Append each directory as a series of '-I' flags in ${include_path} foreach(directory ${CAPNPC_IMPORT_DIRS}) get_filename_component(absolute_path "${directory}" ABSOLUTE) list(APPEND include_path -I "${absolute_path}") endforeach() endif() set(${SOURCES}) set(${HEADERS}) foreach(schema_file ${ARGN}) get_filename_component(file_path "${schema_file}" ABSOLUTE) get_filename_component(file_dir "${file_path}" PATH) if(NOT EXISTS "${file_path}") message(FATAL_ERROR "Cap'n Proto schema file '${file_path}' does not exist!") endif() # Figure out where the output files will go if (NOT DEFINED CAPNPC_OUTPUT_DIR) set(CAPNPC_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/") endif() # Output files are placed in CAPNPC_OUTPUT_DIR, at a location as if they were # relative to CAPNPC_SRC_PREFIX. string(LENGTH "${CAPNPC_SRC_PREFIX}" prefix_len) string(SUBSTRING "${file_path}" 0 ${prefix_len} output_prefix) if(NOT "${CAPNPC_SRC_PREFIX}" STREQUAL "${output_prefix}") message(SEND_ERROR "Could not determine output path for '${schema_file}' ('${file_path}') with source prefix '${CAPNPC_SRC_PREFIX}' into '${CAPNPC_OUTPUT_DIR}'.") endif() string(SUBSTRING "${file_path}" ${prefix_len} -1 output_path) set(output_base "${CAPNPC_OUTPUT_DIR}${output_path}") add_custom_command( OUTPUT "${output_base}.c++" "${output_base}.h" COMMAND "${CAPNP_EXECUTABLE}" ARGS compile -o ${CAPNPC_CXX_EXECUTABLE}${output_dir} --src-prefix ${CAPNPC_SRC_PREFIX} ${include_path} ${CAPNPC_FLAGS} ${file_path} DEPENDS "${schema_file}" ${tool_depends} COMMENT "Compiling Cap'n Proto schema ${schema_file}" VERBATIM ) list(APPEND ${SOURCES} "${output_base}.c++") list(APPEND ${HEADERS} "${output_base}.h") endforeach() set_source_files_properties(${${SOURCES}} ${${HEADERS}} PROPERTIES GENERATED TRUE) set(${SOURCES} ${${SOURCES}} PARENT_SCOPE) set(${HEADERS} ${${HEADERS}} PARENT_SCOPE) endfunction() capnproto-c++-1.1.0/configure0000755000175000017500000240746414731562165016704 0ustar00kentonkenton00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for Capn Proto 1.1.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: capnproto@googlegroups.com about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Capn Proto' PACKAGE_TARNAME='capnproto-c++' PACKAGE_VERSION='1.1.0' PACKAGE_STRING='Capn Proto 1.1.0' PACKAGE_BUGREPORT='capnproto@googlegroups.com' PACKAGE_URL='' ac_unique_file="src/capnp/layout.c++" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS HAS_FUZZING_ENGINE_FALSE HAS_FUZZING_ENGINE_TRUE _WITH_LIBUCONTEXT WITH_OPENSSL BUILD_KJ_TLS_FALSE BUILD_KJ_TLS_TRUE BUILD_KJ_GZIP_FALSE BUILD_KJ_GZIP_TRUE CMAKE_SIZEOF_VOID_P PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR PACKAGE_INIT SO_VERSION CAPNP_CMAKE_CONFIG_FILES CAPNP_PKG_CONFIG_FILES STDLIB_FLAG CAPNP_LITE_FLAG LITE_MODE_FALSE LITE_MODE_TRUE USE_EXTERNAL_CAPNP_FALSE USE_EXTERNAL_CAPNP_TRUE CAPNPC_CXX CAPNP CXXCPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP FILECMD LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL acx_pthread_config host_os host_vendor host_cpu host build_os build_vendor build_cpu build ASYNC_LIBS PTHREAD_CC PTHREAD_CFLAGS PTHREAD_LIBS am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V CSCOPE ETAGS CTAGS am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules with_external_capnp with_zlib with_openssl with_fibers enable_reflection enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC LT_SYS_LIBRARY_PATH CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Capn Proto 1.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/capnproto-c++] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Capn Proto 1.1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --disable-reflection compile Cap'n Proto in "lite mode", in which all reflection APIs (schema.h, dynamic.h, etc.) are not included. Produces a smaller library at the cost of features. All programs built against the library MUST be compiled with -DCAPNP_LITE=1. Note that because the compiler itself uses reflection in its implementation, you must also use --with-external-capnp when using this option. --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-external-capnp use the system capnp binary (or the one specified with $CAPNP) instead of compiling a new one (useful for cross-compiling) --with-zlib build libkj-gzip by linking against zlib [default=check] --with-openssl build libkj-tls by linking against openssl [default=check] --with-fibers build libkj-async with fibers [default=check] --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Capn Proto configure 1.1.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_cxx_try_run LINENO # ------------------------ # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_cxx_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_run # ac_fn_cxx_compute_int LINENO EXPR VAR INCLUDES # ---------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_cxx_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_hi=$ac_mid; break else $as_nop as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_lo=$ac_mid; break else $as_nop as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_hi=$ac_mid else $as_nop as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval (void) { return $2; } static unsigned long int ulongval (void) { return $2; } #include #include int main (void) { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_cxx_try_run "$LINENO" then : echo >>conftest.val; read $3 &5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Capn Proto $as_me 1.1.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " # Test code for whether the C++ compiler supports C++98 (global declarations) ac_cxx_conftest_cxx98_globals=' // Does the compiler advertise C++98 conformance? #if !defined __cplusplus || __cplusplus < 199711L # error "Compiler does not advertise C++98 conformance" #endif // These inclusions are to reject old compilers that // lack the unsuffixed header files. #include #include // and are *not* freestanding headers in C++98. extern void assert (int); namespace std { extern int strcmp (const char *, const char *); } // Namespaces, exceptions, and templates were all added after "C++ 2.0". using std::exception; using std::strcmp; namespace { void test_exception_syntax() { try { throw "test"; } catch (const char *s) { // Extra parentheses suppress a warning when building autoconf itself, // due to lint rules shared with more typical C programs. assert (!(strcmp) (s, "test")); } } template struct test_template { T const val; explicit test_template(T t) : val(t) {} template T add(U u) { return static_cast(u) + val; } }; } // anonymous namespace ' # Test code for whether the C++ compiler supports C++98 (body of main) ac_cxx_conftest_cxx98_main=' assert (argc); assert (! argv[0]); { test_exception_syntax (); test_template tt (2.0); assert (tt.add (4) == 6.0); assert (true && !false); } ' # Test code for whether the C++ compiler supports C++11 (global declarations) ac_cxx_conftest_cxx11_globals=' // Does the compiler advertise C++ 2011 conformance? #if !defined __cplusplus || __cplusplus < 201103L # error "Compiler does not advertise C++11 conformance" #endif namespace cxx11test { constexpr int get_val() { return 20; } struct testinit { int i; double d; }; class delegate { public: delegate(int n) : n(n) {} delegate(): delegate(2354) {} virtual int getval() { return this->n; }; protected: int n; }; class overridden : public delegate { public: overridden(int n): delegate(n) {} virtual int getval() override final { return this->n * 2; } }; class nocopy { public: nocopy(int i): i(i) {} nocopy() = default; nocopy(const nocopy&) = delete; nocopy & operator=(const nocopy&) = delete; private: int i; }; // for testing lambda expressions template Ret eval(Fn f, Ret v) { return f(v); } // for testing variadic templates and trailing return types template auto sum(V first) -> V { return first; } template auto sum(V first, Args... rest) -> V { return first + sum(rest...); } } ' # Test code for whether the C++ compiler supports C++11 (body of main) ac_cxx_conftest_cxx11_main=' { // Test auto and decltype auto a1 = 6538; auto a2 = 48573953.4; auto a3 = "String literal"; int total = 0; for (auto i = a3; *i; ++i) { total += *i; } decltype(a2) a4 = 34895.034; } { // Test constexpr short sa[cxx11test::get_val()] = { 0 }; } { // Test initializer lists cxx11test::testinit il = { 4323, 435234.23544 }; } { // Test range-based for int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; for (auto &x : array) { x += 23; } } { // Test lambda expressions using cxx11test::eval; assert (eval ([](int x) { return x*2; }, 21) == 42); double d = 2.0; assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); assert (d == 5.0); assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); assert (d == 5.0); } { // Test use of variadic templates using cxx11test::sum; auto a = sum(1); auto b = sum(1, 2); auto c = sum(1.0, 2.0, 3.0); } { // Test constructor delegation cxx11test::delegate d1; cxx11test::delegate d2(); cxx11test::delegate d3(45); } { // Test override and final cxx11test::overridden o1(55464); } { // Test nullptr char *c = nullptr; } { // Test template brackets test_template<::test_template> v(test_template(12)); } { // Unicode literals char const *utf8 = u8"UTF-8 string \u2500"; char16_t const *utf16 = u"UTF-8 string \u2500"; char32_t const *utf32 = U"UTF-32 string \u2500"; } ' # Test code for whether the C compiler supports C++11 (complete). ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} ${ac_cxx_conftest_cxx11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} ${ac_cxx_conftest_cxx11_main} return ok; } " # Test code for whether the C compiler supports C++98 (complete). ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} int main (int argc, char **argv) { int ok = 0; ${ac_cxx_conftest_cxx98_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Auxiliary files required by this configure script. ac_aux_files="ltmain.sh config.guess config.sub compile missing install-sh" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}/build-aux" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" # autoconf's default CXXFLAGS are usually "-g -O2". A far more reasonable # default is -O2 -NDEBUG. if test "x${ac_cv_env_CFLAGS_set}" = "x" then : CFLAGS="-O2 -DNDEBUG" fi if test "x${ac_cv_env_CXXFLAGS_set}" = "x" then : CXXFLAGS="-O2 -DNDEBUG" fi am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else $as_nop if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='capnproto-c++' VERSION='1.1.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar plaintar pax cpio none' # The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 printf %s "checking whether UID '$am_uid' is supported by ustar format... " >&6; } if test $am_uid -le $am_max_uid; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } _am_tools=none fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 printf %s "checking whether GID '$am_gid' is supported by ustar format... " >&6; } if test $am_gid -le $am_max_gid; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } _am_tools=none fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 printf %s "checking how to create a ustar tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_ustar-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x ustar -w "$$tardir"' am__tar_='pax -L -x ustar -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H ustar -L' am__tar_='find "$tardir" -print | cpio -o -H ustar -L' am__untar='cpio -i -H ustar -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_ustar}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar &5 ($am__untar &5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if test ${am_cv_prog_tar_ustar+y} then : printf %s "(cached) " >&6 else $as_nop am_cv_prog_tar_ustar=$_am_tool fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 printf "%s\n" "$am_cv_prog_tar_ustar" >&6; } # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi if test -z "$ETAGS"; then ETAGS=etags fi if test -z "$CSCOPE"; then CSCOPE=cscope fi # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --with-external-capnp was given. if test ${with_external_capnp+y} then : withval=$with_external_capnp; external_capnp=yes else $as_nop external_capnp=no fi # Check whether --with-zlib was given. if test ${with_zlib+y} then : withval=$with_zlib; else $as_nop with_zlib=check fi # Check whether --with-openssl was given. if test ${with_openssl+y} then : withval=$with_openssl; else $as_nop with_openssl=check fi # Check whether --with-fibers was given. if test ${with_fibers+y} then : withval=$with_fibers; else $as_nop with_fibers=check fi # Check whether --enable-reflection was given. if test ${enable_reflection+y} then : enableval=$enable_reflection; case "${enableval}" in yes) lite_mode=no ;; no) lite_mode=yes if test "$external_capnp" != "yes" then : as_fn_error $? "you must specify --with-external-capnp when using --disable-reflection" "$LINENO" 5 fi ;; *) as_fn_error $? "bad value ${enableval} for --enable-reflection" "$LINENO" 5 ;; esac else $as_nop lite_mode=no fi # Checks for programs. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test ${enable_dependency_tracking+y} then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 printf "%s\n" "$CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CXX+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 printf "%s\n" "$ac_ct_CXX" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 printf %s "checking whether the compiler supports GNU C++... " >&6; } if test ${ac_cv_cxx_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+y} ac_save_CXXFLAGS=$CXXFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 printf %s "checking whether $CXX accepts -g... " >&6; } if test ${ac_cv_prog_cxx_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes else $as_nop CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : else $as_nop ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } if test $ac_test_CXXFLAGS; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_prog_cxx_stdcxx=no if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 printf %s "checking for $CXX option to enable C++11 features... " >&6; } if test ${ac_cv_prog_cxx_cxx11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx11=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx11_program _ACEOF for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx11" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx11" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 ac_prog_cxx_stdcxx=cxx11 fi fi if test x$ac_prog_cxx_stdcxx = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 printf %s "checking for $CXX option to enable C++98 features... " >&6; } if test ${ac_cv_prog_cxx_cxx98+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cxx_cxx98=no ac_save_CXX=$CXX cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_cxx_conftest_cxx98_program _ACEOF for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA do CXX="$ac_save_CXX $ac_arg" if ac_fn_cxx_try_compile "$LINENO" then : ac_cv_prog_cxx_cxx98=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cxx_cxx98" != "xno" && break done rm -f conftest.$ac_ext CXX=$ac_save_CXX fi if test "x$ac_cv_prog_cxx_cxx98" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cxx_cxx98" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } CXX="$CXX $ac_cv_prog_cxx_cxx98" fi ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 ac_prog_cxx_stdcxx=cxx98 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CXX_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features by default" >&5 printf %s "checking whether $CXX supports C++14 features by default... " >&6; } if test ${ax_cv_cxx_compile_cxx14+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); // GCC 4.7 introduced __float128 and makes reference to it in type_traits. // Clang doesn't implement it, so produces an error. Using -std=c++11 // instead of -std=gnu++11 works around the problem. But on some // platforms we need -std=gnu++11. So we want to make sure the test of // -std=gnu++11 fails only where this problem is present, and we hope that // -std=c++11 is always an acceptable fallback in these cases. Complicating // matters, though, is that we don't want to fail here if the platform is // completely missing a C++11 standard library, because we want to probe that // in a later test. It happens, though, that Clang allows us to check // whether a header exists at all before we include it. // // So, if we detect that __has_include is available (which it is on Clang), // and we use it to detect that (a C++11 header) exists, then // we go ahead and #include it to see if it breaks. In all other cases, we // don't #include it at all. #ifdef __has_include #if __has_include() #include #endif #endif // C++14 stuff auto deduceReturnType(int i) { return i; } auto genericLambda = [](auto x, auto y) { return x + y; }; auto captureExpressions = [x = 123]() { return x; }; // Avoid unused variable warnings. int foo() { return genericLambda(1, 2) + captureExpressions(); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ax_cv_cxx_compile_cxx14=yes else $as_nop ax_cv_cxx_compile_cxx14=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx14" >&5 printf "%s\n" "$ax_cv_cxx_compile_cxx14" >&6; } if test x$ax_cv_cxx_compile_cxx14 = xyes; then ac_success=yes fi if test x$ac_success = xno; then for switch in -std=gnu++14 -std=gnu++1y; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx14_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 printf %s "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); // GCC 4.7 introduced __float128 and makes reference to it in type_traits. // Clang doesn't implement it, so produces an error. Using -std=c++11 // instead of -std=gnu++11 works around the problem. But on some // platforms we need -std=gnu++11. So we want to make sure the test of // -std=gnu++11 fails only where this problem is present, and we hope that // -std=c++11 is always an acceptable fallback in these cases. Complicating // matters, though, is that we don't want to fail here if the platform is // completely missing a C++11 standard library, because we want to probe that // in a later test. It happens, though, that Clang allows us to check // whether a header exists at all before we include it. // // So, if we detect that __has_include is available (which it is on Clang), // and we use it to detect that (a C++11 header) exists, then // we go ahead and #include it to see if it breaks. In all other cases, we // don't #include it at all. #ifdef __has_include #if __has_include() #include #endif #endif // C++14 stuff auto deduceReturnType(int i) { return i; } auto genericLambda = [](auto x, auto y) { return x + y; }; auto captureExpressions = [x = 123]() { return x; }; // Avoid unused variable warnings. int foo() { return genericLambda(1, 2) + captureExpressions(); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" ac_success=yes break fi done fi if test x$ac_success = xno; then for switch in -std=c++14 -std=c++1y; do cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx14_$switch" | $as_tr_sh` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 printf %s "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX $switch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); // GCC 4.7 introduced __float128 and makes reference to it in type_traits. // Clang doesn't implement it, so produces an error. Using -std=c++11 // instead of -std=gnu++11 works around the problem. But on some // platforms we need -std=gnu++11. So we want to make sure the test of // -std=gnu++11 fails only where this problem is present, and we hope that // -std=c++11 is always an acceptable fallback in these cases. Complicating // matters, though, is that we don't want to fail here if the platform is // completely missing a C++11 standard library, because we want to probe that // in a later test. It happens, though, that Clang allows us to check // whether a header exists at all before we include it. // // So, if we detect that __has_include is available (which it is on Clang), // and we use it to detect that (a C++11 header) exists, then // we go ahead and #include it to see if it breaks. In all other cases, we // don't #include it at all. #ifdef __has_include #if __has_include() #include #endif #endif // C++14 stuff auto deduceReturnType(int i) { return i; } auto genericLambda = [](auto x, auto y) { return x + y; }; auto captureExpressions = [x = 123]() { return x; }; // Avoid unused variable warnings. int foo() { return genericLambda(1, 2) + captureExpressions(); } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval $cachevar=yes else $as_nop eval $cachevar=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi eval ac_res=\$$cachevar { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" ac_success=yes break fi done fi if test x$ac_success = xno; then as_fn_error $? "*** A compiler with support for C++14 language features is required." "$LINENO" 5 else ac_success=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 library features by default" >&5 printf %s "checking whether $CXX supports C++11 library features by default... " >&6; } if test ${ax_cv_cxx_compile_cxx11_lib+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : ax_cv_cxx_compile_cxx11_lib=yes else $as_nop ax_cv_cxx_compile_cxx11_lib=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11_lib" >&5 printf "%s\n" "$ax_cv_cxx_compile_cxx11_lib" >&6; } if test x$ax_cv_cxx_compile_cxx11_lib = xyes; then ac_success=yes else # Try with -stdlib=libc++ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 library features with -stdlib=libc++" >&5 printf %s "checking whether $CXX supports C++11 library features with -stdlib=libc++... " >&6; } if test ${ax_cv_cxx_compile_cxx11_lib_libcxx+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_CXX="$CXX" CXX="$CXX -stdlib=libc++" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : eval ax_cv_cxx_compile_cxx11_lib_libcxx=yes else $as_nop eval ax_cv_cxx_compile_cxx11_lib_libcxx=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CXX="$ac_save_CXX" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11_lib_libcxx" >&5 printf "%s\n" "$ax_cv_cxx_compile_cxx11_lib_libcxx" >&6; } if eval test x$ax_cv_cxx_compile_cxx11_lib_libcxx = xyes; then CXX="$CXX -stdlib=libc++" ac_success=yes break fi fi if test x$ac_success = xno; then as_fn_error $? "*** A C++ library with support for C++11 features is required." "$LINENO" 5 fi fi # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac case "${host_os}" in #( *mingw*) : # We don't use pthreads on MinGW. PTHREAD_CFLAGS="-mthreads" PTHREAD_LIBS="" PTHREAD_CC="" ASYNC_LIBS="-lws2_32" ;; #( *) : ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 printf %s "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pthread_join (); int main (void) { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 printf "%s\n" "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 printf %s "checking whether pthreads work without any flags... " >&6; } ;; -*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 printf %s "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_acx_pthread_config+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 printf "%s\n" "$acx_pthread_config" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 printf %s "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 printf "%s\n" "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 printf %s "checking for joinable pthread attribute... " >&6; } attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int attr=$attr; return attr; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : attr_name=$attr; break fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 printf "%s\n" "$attr_name" >&6; } if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then printf "%s\n" "#define PTHREAD_CREATE_JOINABLE $attr_name" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 printf %s "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 printf "%s\n" "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then for ac_prog in xlc_r cc_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_PTHREAD_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 printf "%s\n" "$PTHREAD_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" else PTHREAD_CC=$CC fi # The next part tries to detect GCC inconsistency with -shared on some # architectures and systems. The problem is that in certain # configurations, when -shared is specified, GCC "forgets" to # internally use various flags which are still necessary. # # Prepare the flags # save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" # Try with the flags determined by the earlier checks. # # -Wl,-z,defs forces link-time symbol resolution, so that the # linking checks with -shared actually have any value # # FIXME: -fPIC is required for -shared on many architectures, # so we specify it here, but the right way would probably be to # properly detect whether it is actually required. CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CC="$PTHREAD_CC" # In order not to create several levels of indentation, we test # the value of "$done" until we find the cure or run out of ideas. done="no" # First, make sure the CFLAGS we added are actually accepted by our # compiler. If not (and OS X's ld, for instance, does not accept -z), # then we can't do this test. if test x"$done" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to check for GCC pthread/shared inconsistencies" >&5 printf %s "checking whether to check for GCC pthread/shared inconsistencies... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : else $as_nop done=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi fi if test x"$done" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -pthread is sufficient with -shared" >&5 printf %s "checking whether -pthread is sufficient with -shared... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : done=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi # # Linux gcc on some architectures such as mips/mipsel forgets # about -lpthread # if test x"$done" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lpthread fixes that" >&5 printf %s "checking whether -lpthread fixes that... " >&6; } LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : done=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi # # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc # if test x"$done" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc_r fixes that" >&5 printf %s "checking whether -lc_r fixes that... " >&6; } LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : done=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test x"$done" = xno; then # OK, we have run out of ideas { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Impossible to determine how to use pthreads with shared libraries" >&5 printf "%s\n" "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries" >&2;} # so it's not safe to assume that we may use pthreads acx_pthread_ok=no fi CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" else PTHREAD_CC="$CC" fi if test "x$acx_pthread_ok" = xyes; then # One more check: If we chose to use a compiler flag like -pthread but it is combined with # -nostdlib then the compiler won't implicitly link against libpthread. This can happen # in particular when using some versions of libtool on some distros. See: # https://bugzilla.redhat.com/show_bug.cgi?id=661333 save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="-nostdlib $PTHREAD_LIBS $LIBS -lc" CC="$PTHREAD_CC" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthread flag is sufficient with -nostdlib" >&5 printf %s "checking whether pthread flag is sufficient with -nostdlib... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether adding -lpthread fixes that" >&5 printf %s "checking whether adding -lpthread fixes that... " >&6; } LIBS="-nostdlib $PTHREAD_LIBS -lpthread $save_LIBS -lc" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h : else acx_pthread_ok=no fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ASYNC_LIBS="" ;; #( *) : ;; esac case `pwd` in *\ * | *\ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.7' macro_revision='2.4.7' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 printf %s "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5 printf "%s\n" "printf" >&6; } ;; print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 printf "%s\n" "print -r" >&6; } ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5 printf "%s\n" "cat" >&6; } ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 printf %s "checking for a sed that does not truncate output... " >&6; } if test ${ac_cv_path_SED+y} then : printf %s "(cached) " >&6 else $as_nop ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in sed gsed do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 printf "%s\n" "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 printf %s "checking for fgrep... " >&6; } if test ${ac_cv_path_FGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in fgrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 printf "%s\n" "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else $as_nop with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else $as_nop # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test ${lt_cv_path_NM+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 printf "%s\n" "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DUMPBIN+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 printf "%s\n" "$DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DUMPBIN+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 printf "%s\n" "$ac_ct_DUMPBIN" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 printf %s "checking the name lister ($NM) interface... " >&6; } if test ${lt_cv_nm_interface+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 printf "%s\n" "$lt_cv_nm_interface" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 printf "%s\n" "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 printf %s "checking the maximum length of command line arguments... " >&6; } if test ${lt_cv_sys_max_cmd_len+y} then : printf %s "(cached) " >&6 else $as_nop i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 printf %s "checking how to convert $build file names to $host format... " >&6; } if test ${lt_cv_to_host_file_cmd+y} then : printf %s "(cached) " >&6 else $as_nop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 printf %s "checking how to convert $build file names to toolchain format... " >&6; } if test ${lt_cv_to_tool_file_cmd+y} then : printf %s "(cached) " >&6 else $as_nop #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 printf %s "checking for $LD option to reload object files... " >&6; } if test ${lt_cv_ld_reload_flag+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_reload_flag='-r' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 printf "%s\n" "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. set dummy ${ac_tool_prefix}file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_FILECMD+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$FILECMD"; then ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_FILECMD="${ac_tool_prefix}file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi FILECMD=$ac_cv_prog_FILECMD if test -n "$FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 printf "%s\n" "$FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_FILECMD"; then ac_ct_FILECMD=$FILECMD # Extract the first word of "file", so it can be a program name with args. set dummy file; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_FILECMD+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_FILECMD"; then ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_FILECMD="file" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD if test -n "$ac_ct_FILECMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 printf "%s\n" "$ac_ct_FILECMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_FILECMD" = x; then FILECMD=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac FILECMD=$ac_ct_FILECMD fi else FILECMD="$ac_cv_prog_FILECMD" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OBJDUMP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 printf "%s\n" "$OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OBJDUMP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 printf "%s\n" "$ac_ct_OBJDUMP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 printf %s "checking how to recognize dependent libraries... " >&6; } if test ${lt_cv_deplibs_check_method+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 printf "%s\n" "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DLLTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 printf "%s\n" "$DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DLLTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 printf "%s\n" "$ac_ct_DLLTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 printf %s "checking how to associate runtime and link libraries... " >&6; } if test ${lt_cv_sharedlib_from_linklib_cmd+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 printf %s "checking for archiver @FILE support... " >&6; } if test ${lt_cv_ar_at_file+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 printf "%s\n" "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 printf %s "checking command to parse $NM output from $compiler object... " >&6; } if test ${lt_cv_sys_global_symbol_pipe+y} then : printf %s "(cached) " >&6 else $as_nop # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5 printf "%s\n" "failed" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5 printf "%s\n" "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 printf %s "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test ${with_sysroot+y} then : withval=$with_sysroot; else $as_nop with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 printf "%s\n" "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 printf "%s\n" "${lt_sysroot:-no}" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 printf %s "checking for a working dd... " >&6; } if test ${ac_cv_path_lt_DD+y} then : printf %s "(cached) " >&6 else $as_nop printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in dd do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 printf "%s\n" "$ac_cv_path_lt_DD" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 printf %s "checking how to truncate binary pipes... " >&6; } if test ${lt_cv_truncate_bin+y} then : printf %s "(cached) " >&6 else $as_nop printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 printf "%s\n" "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test ${enable_libtool_lock+y} then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 printf %s "checking whether the C compiler needs -belf... " >&6; } if test ${lt_cv_cc_needs_belf+y} then : printf %s "(cached) " >&6 else $as_nop ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_cc_needs_belf=yes else $as_nop lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 printf "%s\n" "$MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if test ${lt_cv_path_mainfest_tool+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_DSYMUTIL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 printf "%s\n" "$DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_DSYMUTIL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 printf "%s\n" "$ac_ct_DSYMUTIL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_NMEDIT+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 printf "%s\n" "$NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_NMEDIT+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 printf "%s\n" "$ac_ct_NMEDIT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_LIPO+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 printf "%s\n" "$LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_LIPO+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 printf "%s\n" "$ac_ct_LIPO" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 printf "%s\n" "$OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 printf "%s\n" "$ac_ct_OTOOL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_OTOOL64+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 printf "%s\n" "$OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_OTOOL64+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 printf "%s\n" "$ac_ct_OTOOL64" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 printf %s "checking for -single_module linker flag... " >&6; } if test ${lt_cv_apple_cc_single_mod+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 printf %s "checking for -exported_symbols_list linker flag... " >&6; } if test ${lt_cv_ld_exported_symbols_list+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_ld_exported_symbols_list=yes else $as_nop lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 printf %s "checking for -force_load linker flag... " >&6; } if test ${lt_cv_ld_force_load+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 printf "%s\n" "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[012],*|,*powerpc*-darwin[5-8]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes then : printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h fi func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_shared=yes fi # Check whether --enable-static was given. if test ${enable_static+y} then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_static=yes fi # Check whether --with-pic was given. if test ${with_pic+y} then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop pic_mode=default fi # Check whether --enable-fast-install was given. if test ${enable_fast_install+y} then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else $as_nop enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 printf %s "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test ${with_aix_soname+y} then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else $as_nop if test ${lt_cv_with_aix_soname+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 printf "%s\n" "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 printf %s "checking for objdir... " >&6; } if test ${lt_cv_objdir+y} then : printf %s "(cached) " >&6 else $as_nop rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 printf "%s\n" "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 printf %s "checking for ${ac_tool_prefix}file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5 printf %s "checking for file... " >&6; } if test ${lt_cv_path_MAGIC_CMD+y} then : printf %s "(cached) " >&6 else $as_nop case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 printf "%s\n" "$MAGIC_CMD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test ${lt_cv_prog_compiler_rtti_exceptions+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test ${lt_cv_prog_compiler_pic_works+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath_+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly* | midnightbsd*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 printf %s "checking if $CC understands -b... " >&6; } if test ${lt_cv_prog_compiler__b+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 printf "%s\n" "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if test ${lt_cv_irix_exported_symbol+y} then : printf %s "(cached) " >&6 else $as_nop save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : lt_cv_irix_exported_symbol=yes else $as_nop lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 printf "%s\n" "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc+y} then : printf %s "(cached) " >&6 else $as_nop $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 printf "%s\n" "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else $as_nop lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes then : lt_cv_dlopen=shl_load else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shl_load (); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else $as_nop ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else $as_nop ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes then : lt_cv_dlopen=dlopen else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 printf %s "checking for dlopen in -ldl... " >&6; } if test ${ac_cv_lib_dl_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dl_dlopen=yes else $as_nop ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 printf %s "checking for dlopen in -lsvld... " >&6; } if test ${ac_cv_lib_svld_dlopen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dlopen (); int main (void) { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_svld_dlopen=yes else $as_nop ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 printf %s "checking for dld_link in -ldld... " >&6; } if test ${ac_cv_lib_dld_dld_link+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dld_link (); int main (void) { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_dld_link=yes else $as_nop ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 printf %s "checking whether a program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self+y} then : printf %s "(cached) " >&6 else $as_nop if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 printf "%s\n" "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 printf %s "checking whether a statically linked program can dlopen itself... " >&6; } if test ${lt_cv_dlopen_self_static+y} then : printf %s "(cached) " >&6 else $as_nop if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 printf "%s\n" "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 printf %s "checking whether stripping libraries is possible... " >&6; } if test -z "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } ;; esac fi fi # Report what library types will actually be built { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 printf %s "checking if libtool supports shared libraries... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 printf "%s\n" "$can_build_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 printf %s "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 printf "%s\n" "$enable_shared" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 printf %s "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 printf "%s\n" "$enable_static" >&6; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 printf %s "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if test ${ac_cv_prog_CXXCPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CXX needs to be expanded for CXXCPP in "$CXX -E" cpp /lib/cpp do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 printf "%s\n" "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test ${with_gnu_ld+y} then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else $as_nop with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 printf %s "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 printf %s "checking for GNU ld... " >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 printf %s "checking for non-GNU ld... " >&6; } fi if test ${lt_cv_path_LD+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 printf "%s\n" "$LD" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 printf %s "checking if the linker ($LD) is GNU ld... " >&6; } if test ${lt_cv_prog_gnu_ld+y} then : printf %s "(cached) " >&6 else $as_nop # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if test ${lt_cv_aix_libpath__CXX+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes file_list_spec_CXX='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 printf %s "checking for $compiler option to produce PIC... " >&6; } if test ${lt_cv_prog_compiler_pic_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if test ${lt_cv_prog_compiler_pic_works_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test ${lt_cv_prog_compiler_static_works_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test ${lt_cv_prog_compiler_c_o_CXX+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 printf %s "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 printf "%s\n" "$hard_links" >&6; } if test no = "$hard_links"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 printf "%s\n" "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 printf %s "checking whether -lc should be explicitly linked in... " >&6; } if test ${lt_cv_archive_cmds_need_lc_CXX+y} then : printf %s "(cached) " >&6 else $as_nop $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 printf "%s\n" "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 printf %s "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if test ${lt_cv_shlibpath_overrides_runpath+y} then : printf %s "(cached) " >&6 else $as_nop lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 printf "%s\n" "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 printf %s "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 printf "%s\n" "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: if test "$external_capnp" != "no" then : if test "x$CAPNP" = "x" then : CAPNP="capnp" else $as_nop with_capnp=yes fi if test "x$CAPNPC_CXX" = "x" then : # CAPNPC_CXX was not specified. Choose a reasonable default. case $CAPNP in #( */*) : # $CAPNP contains a slash, so it's not on $PATH. Assume capnpc-c++ is not either, but is # in the same directory. CAPNPC_CXX=`dirname $CAPNP`/capnpc-c++ ;; #( *) : # $CAPNP is on $PATH, so tell it to find the plugin on $PATH as well. CAPNPC_CXX="c++" ;; esac fi fi if test "$external_capnp" != "no"; then USE_EXTERNAL_CAPNP_TRUE= USE_EXTERNAL_CAPNP_FALSE='#' else USE_EXTERNAL_CAPNP_TRUE='#' USE_EXTERNAL_CAPNP_FALSE= fi if test "$lite_mode" = "yes"; then LITE_MODE_TRUE= LITE_MODE_FALSE='#' else LITE_MODE_TRUE='#' LITE_MODE_FALSE= fi if test "$lite_mode" = "yes" then : CXXFLAGS="-DCAPNP_LITE $CXXFLAGS" CAPNP_LITE_FLAG=-DCAPNP_LITE fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing sched_yield" >&5 printf %s "checking for library containing sched_yield... " >&6; } if test ${ac_cv_search_sched_yield+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int sched_yield (); } int main (void) { return conftest::sched_yield (); ; return 0; } _ACEOF for ac_lib in '' rt do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_cxx_try_link "$LINENO" then : ac_cv_search_sched_yield=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_sched_yield+y} then : break fi done if test ${ac_cv_search_sched_yield+y} then : else $as_nop ac_cv_search_sched_yield=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sched_yield" >&5 printf "%s\n" "$ac_cv_search_sched_yield" >&6; } ac_res=$ac_cv_search_sched_yield if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # Users will need to use the same -stdlib as us so we'd better let pkg-config know about it. STDLIB_FLAG=`echo "$CXX $CXXFLAGS" | grep -o ' [-]stdlib=[^ ]*'` LIBS="$PTHREAD_LIBS $LIBS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" CAPNP_PKG_CONFIG_FILES=" \ pkgconfig/capnp.pc \ pkgconfig/capnpc.pc \ pkgconfig/capnp-rpc.pc \ pkgconfig/capnp-json.pc \ pkgconfig/capnp-websocket.pc \ pkgconfig/kj.pc \ pkgconfig/kj-async.pc \ pkgconfig/kj-http.pc \ pkgconfig/kj-gzip.pc \ pkgconfig/kj-tls.pc \ pkgconfig/kj-test.pc \ " CAPNP_CMAKE_CONFIG_FILES=" \ cmake/CapnProtoConfig.cmake \ cmake/CapnProtoConfigVersion.cmake \ " # Don't include security release in soname -- we want to replace old binaries # in this case. SO_VERSION=$(echo $VERSION | sed -e 's/^\(0-9*.0-9*.0-9*\)\(.0-9*\)*\(-.*\)*$/\1\3/g') # CapnProtoConfig.cmake.in needs these PACKAGE_* output variables. PACKAGE_INIT="set(CAPNP_PKG_CONFIG_FILES \ pkgconfig/capnp.pc \ pkgconfig/capnpc.pc \ pkgconfig/capnp-rpc.pc \ pkgconfig/capnp-json.pc \ pkgconfig/capnp-websocket.pc \ pkgconfig/kj.pc \ pkgconfig/kj-async.pc \ pkgconfig/kj-http.pc \ pkgconfig/kj-gzip.pc \ pkgconfig/kj-tls.pc \ pkgconfig/kj-test.pc \ )" PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR="\${CMAKE_CURRENT_LIST_DIR}/../../../include" # CapnProtoConfigVersion.cmake.in needs PACKAGE_VERSION (already defined by AC_INIT) and # CMAKE_SIZEOF_VOID_P output variables. # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 printf %s "checking size of void *... " >&6; } if test ${ac_cv_sizeof_void_p+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_void_p" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (void *) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_void_p=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 printf "%s\n" "$ac_cv_sizeof_void_p" >&6; } printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h CMAKE_SIZEOF_VOID_P=$ac_cv_sizeof_void_p # Detect presence of zlib, if it was not specified explicitly. if test "$with_zlib" = check then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 printf %s "checking for deflate in -lz... " >&6; } if test ${ac_cv_lib_z_deflate+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int deflate (); } int main (void) { return conftest::deflate (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : ac_cv_lib_z_deflate=yes else $as_nop ac_cv_lib_z_deflate=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 printf "%s\n" "$ac_cv_lib_z_deflate" >&6; } if test "x$ac_cv_lib_z_deflate" = xyes then : : else $as_nop with_zlib=no fi ac_fn_cxx_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes then : : else $as_nop with_zlib=no fi if test "$with_zlib" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: \"could not find zlib -- won't build libkj-gzip\"" >&5 printf "%s\n" "$as_me: WARNING: \"could not find zlib -- won't build libkj-gzip\"" >&2;} else $as_nop with_zlib=yes fi fi if test "$with_zlib" != no then : CXXFLAGS="$CXXFLAGS -DKJ_HAS_ZLIB" fi if test "$with_zlib" != no; then BUILD_KJ_GZIP_TRUE= BUILD_KJ_GZIP_FALSE='#' else BUILD_KJ_GZIP_TRUE='#' BUILD_KJ_GZIP_FALSE= fi # Detect presence of OpenSSL, if it was not specified explicitly. if test "$with_openssl" = check then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5 printf %s "checking for CRYPTO_new_ex_data in -lcrypto... " >&6; } if test ${ac_cv_lib_crypto_CRYPTO_new_ex_data+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int CRYPTO_new_ex_data (); } int main (void) { return conftest::CRYPTO_new_ex_data (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : ac_cv_lib_crypto_CRYPTO_new_ex_data=yes else $as_nop ac_cv_lib_crypto_CRYPTO_new_ex_data=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CRYPTO_new_ex_data" >&5 printf "%s\n" "$ac_cv_lib_crypto_CRYPTO_new_ex_data" >&6; } if test "x$ac_cv_lib_crypto_CRYPTO_new_ex_data" = xyes then : : else $as_nop with_openssl=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OPENSSL_init_ssl in -lssl" >&5 printf %s "checking for OPENSSL_init_ssl in -lssl... " >&6; } if test ${ac_cv_lib_ssl_OPENSSL_init_ssl+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lssl -lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int OPENSSL_init_ssl (); } int main (void) { return conftest::OPENSSL_init_ssl (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : ac_cv_lib_ssl_OPENSSL_init_ssl=yes else $as_nop ac_cv_lib_ssl_OPENSSL_init_ssl=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_OPENSSL_init_ssl" >&5 printf "%s\n" "$ac_cv_lib_ssl_OPENSSL_init_ssl" >&6; } if test "x$ac_cv_lib_ssl_OPENSSL_init_ssl" = xyes then : : else $as_nop with_openssl=no fi ac_fn_cxx_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_ssl_h" = xyes then : : else $as_nop with_openssl=no fi if test "$with_openssl" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: \"could not find OpenSSL -- won't build libkj-tls\"" >&5 printf "%s\n" "$as_me: WARNING: \"could not find OpenSSL -- won't build libkj-tls\"" >&2;} else $as_nop with_openssl=yes fi fi if test "$with_openssl" != no then : CXXFLAGS="$CXXFLAGS -DKJ_HAS_OPENSSL" fi if test "$with_openssl" != no; then BUILD_KJ_TLS_TRUE= BUILD_KJ_TLS_FALSE='#' else BUILD_KJ_TLS_TRUE='#' BUILD_KJ_TLS_FALSE= fi # Fibers don't work if exceptions are disabled, so default off in that case. if test "$with_fibers" != no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if exceptions are enabled" >&5 printf %s "checking if exceptions are enabled... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ void foo() { throw 1; } _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop if test "$with_fibers" = check then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no -- therefore, disabling fibers" >&5 printf "%s\n" "no -- therefore, disabling fibers" >&6; } with_fibers=no else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "Fibers require exceptions, but your compiler flags disable exceptions. Please either enable exceptions or disable fibers (--without-fibers)." "$LINENO" 5 fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi # Check for library support necessary for fibers. if test "$with_fibers" != no then : case "${host_os}" in cygwin* | mingw* ) # Fibers always work on Windows, where there's an explicit API for them. with_fibers=yes ;; * ) # Fibers need the symbols getcontext, setcontext, swapcontext and makecontext. # We assume that makecontext implies the rest. libc_supports_fibers=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing makecontext" >&5 printf %s "checking for library containing makecontext... " >&6; } if test ${ac_cv_search_makecontext+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int makecontext (); } int main (void) { return conftest::makecontext (); ; return 0; } _ACEOF for ac_lib in '' do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_cxx_try_link "$LINENO" then : ac_cv_search_makecontext=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_makecontext+y} then : break fi done if test ${ac_cv_search_makecontext+y} then : else $as_nop ac_cv_search_makecontext=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_makecontext" >&5 printf "%s\n" "$ac_cv_search_makecontext" >&6; } ac_res=$ac_cv_search_makecontext if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else $as_nop libc_supports_fibers=no fi if test "$libc_supports_fibers" = yes then : with_fibers=yes else $as_nop # If getcontext does not exist in libc, try with libucontext ucontext_supports_fibers=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for makecontext in -lucontext" >&5 printf %s "checking for makecontext in -lucontext... " >&6; } if test ${ac_cv_lib_ucontext_makecontext+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lucontext $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace conftest { extern "C" int makecontext (); } int main (void) { return conftest::makecontext (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO" then : ac_cv_lib_ucontext_makecontext=yes else $as_nop ac_cv_lib_ucontext_makecontext=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucontext_makecontext" >&5 printf "%s\n" "$ac_cv_lib_ucontext_makecontext" >&6; } if test "x$ac_cv_lib_ucontext_makecontext" = xyes then : printf "%s\n" "#define HAVE_LIBUCONTEXT 1" >>confdefs.h LIBS="-lucontext $LIBS" else $as_nop ucontext_supports_fibers=no fi if test "$ucontext_supports_fibers" = yes then : ASYNC_LIBS="$ASYNC_LIBS -lucontext" with_fibers=yes else $as_nop if test "$with_fibers" = yes then : as_fn_error $? "Missing symbols required for fibers (makecontext, setcontext, ...). Disable fibers (--without-fibers) or install libucontext" "$LINENO" 5 else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: could not find required symbols (makecontext, setcontext, ...) -- won't build with fibers" >&5 printf "%s\n" "$as_me: WARNING: could not find required symbols (makecontext, setcontext, ...) -- won't build with fibers" >&2;} with_fibers=no fi fi fi ;; esac fi if test "$with_fibers" = yes then : CXXFLAGS="$CXXFLAGS -DKJ_USE_FIBERS" else $as_nop CXXFLAGS="$CXXFLAGS -DKJ_USE_FIBERS=0" fi # CapnProtoConfig.cmake.in needs these variables, # we force them to NO because we don't need the CMake dependency for them, # the dependencies are provided by the .pc files. WITH_OPENSSL=NO _WITH_LIBUCONTEXT=NO if test "x$LIB_FUZZING_ENGINE" != "x"; then HAS_FUZZING_ENGINE_TRUE= HAS_FUZZING_ENGINE_FALSE='#' else HAS_FUZZING_ENGINE_TRUE='#' HAS_FUZZING_ENGINE_FALSE= fi ac_config_files="$ac_config_files Makefile pkgconfig/capnp.pc pkgconfig/capnpc.pc pkgconfig/capnp-rpc.pc pkgconfig/capnp-json.pc pkgconfig/capnp-websocket.pc pkgconfig/kj.pc pkgconfig/kj-async.pc pkgconfig/kj-http.pc pkgconfig/kj-gzip.pc pkgconfig/kj-tls.pc pkgconfig/kj-test.pc cmake/CapnProtoConfig.cmake cmake/CapnProtoConfigVersion.cmake" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 printf "%s\n" "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_EXTERNAL_CAPNP_TRUE}" && test -z "${USE_EXTERNAL_CAPNP_FALSE}"; then as_fn_error $? "conditional \"USE_EXTERNAL_CAPNP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LITE_MODE_TRUE}" && test -z "${LITE_MODE_FALSE}"; then as_fn_error $? "conditional \"LITE_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_KJ_GZIP_TRUE}" && test -z "${BUILD_KJ_GZIP_FALSE}"; then as_fn_error $? "conditional \"BUILD_KJ_GZIP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_KJ_TLS_TRUE}" && test -z "${BUILD_KJ_TLS_FALSE}"; then as_fn_error $? "conditional \"BUILD_KJ_TLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_FUZZING_ENGINE_TRUE}" && test -z "${HAS_FUZZING_ENGINE_FALSE}"; then as_fn_error $? "conditional \"HAS_FUZZING_ENGINE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Capn Proto $as_me 1.1.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ Capn Proto config.status 1.1.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgconfig/capnp.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/capnp.pc" ;; "pkgconfig/capnpc.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/capnpc.pc" ;; "pkgconfig/capnp-rpc.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/capnp-rpc.pc" ;; "pkgconfig/capnp-json.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/capnp-json.pc" ;; "pkgconfig/capnp-websocket.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/capnp-websocket.pc" ;; "pkgconfig/kj.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj.pc" ;; "pkgconfig/kj-async.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj-async.pc" ;; "pkgconfig/kj-http.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj-http.pc" ;; "pkgconfig/kj-gzip.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj-gzip.pc" ;; "pkgconfig/kj-tls.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj-tls.pc" ;; "pkgconfig/kj-test.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/kj-test.pc" ;; "cmake/CapnProtoConfig.cmake") CONFIG_FILES="$CONFIG_FILES cmake/CapnProtoConfig.cmake" ;; "cmake/CapnProtoConfigVersion.cmake") CONFIG_FILES="$CONFIG_FILES cmake/CapnProtoConfigVersion.cmake" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # A file(cmd) program that detects file types. FILECMD=$lt_FILECMD # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive (by configure). lt_ar_flags=$lt_ar_flags # Flags to create an archive. AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi capnproto-c++-1.1.0/LICENSE.txt0000644000175000017500000000231714527152321016572 0ustar00kentonkenton00000000000000Copyright (c) 2013-2017 Sandstorm Development Group, Inc.; Cloudflare, Inc.; and other contributors. Each commit is copyright by its respective author or author's employer. Licensed under the MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. capnproto-c++-1.1.0/Makefile.am0000644000175000017500000007525614712011043017006 0ustar00kentonkenton00000000000000## Process this file with automake to produce Makefile.in ACLOCAL_AMFLAGS = -I m4 # We use serial-tests so that test output will be written directly to stdout # which is much preferred in CI environments where the test logs may be hard # to get at after the fact. Most of our tests are bundled into a single # executable anyway so cannot easily be parallelized. AUTOMAKE_OPTIONS = foreign subdir-objects serial-tests # When running distcheck, verify that we've included all the files needed by # the cmake build. distcheck-hook: rm -rf distcheck-cmake (mkdir distcheck-cmake && cd distcheck-cmake && cmake ../$(distdir) && make -j6 check) rm -rf distcheck-cmake AM_CXXFLAGS = -I$(srcdir)/src -I$(builddir)/src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR='"$(includedir)"' $(PTHREAD_CFLAGS) AM_LDFLAGS = $(PTHREAD_CFLAGS) EXTRA_DIST = \ README.txt \ LICENSE.txt \ $(test_capnpc_inputs) \ src/capnp/compiler/capnp-test.sh \ src/capnp/testdata/segmented-packed \ src/capnp/testdata/errors.capnp.nobuild \ src/capnp/testdata/errors2.capnp.nobuild \ src/capnp/testdata/no-file-id.capnp.nobuild \ src/capnp/testdata/short.txt \ src/capnp/testdata/flat \ src/capnp/testdata/binary \ src/capnp/testdata/errors.txt \ src/capnp/testdata/errors2.txt \ src/capnp/testdata/segmented \ src/capnp/testdata/packed \ src/capnp/testdata/pretty.txt \ src/capnp/testdata/lists.binary \ src/capnp/testdata/packedflat \ src/capnp/testdata/pretty.json \ src/capnp/testdata/short.json \ src/capnp/testdata/annotated-json.binary \ src/capnp/testdata/annotated.json \ CMakeLists.txt \ cmake/CapnProtoMacros.cmake \ cmake/CapnProtoTargets.cmake \ cmake/CapnProtoConfig.cmake.in \ cmake/CapnProtoConfigVersion.cmake.in \ src/CMakeLists.txt \ src/kj/CMakeLists.txt \ src/capnp/CMakeLists.txt CLEANFILES = $(test_capnpc_outputs) test_capnpc_middleman distcheck-cmake # Deletes all the files generated by autoreconf. MAINTAINERCLEANFILES = \ aclocal.m4 \ config.guess \ config.sub \ configure \ depcomp \ install-sh \ ltmain.sh \ Makefile.in \ missing \ mkinstalldirs \ config.h.in \ stamp.h.in \ m4/ltsugar.m4 \ m4/libtool.m4 \ m4/ltversion.m4 \ m4/lt~obsolete.m4 \ m4/ltoptions.m4 maintainer-clean-local: -rm -rf build-aux # gmake defines an implicit rule building n from n.o. Unfortunately, this triggers on our .capnp # files because they generate .capnp.c++ which is compiled to .capnp.o. In addition to being # nonsense, this leads to cyclic dependency issues and could even cause the .capnp files to be # unexpectedly overwritten! We need to cancel the implicit rule by declaring an explicit one. # # I want the hours of my life back that I spent figuring this out. %.capnp: @: public_capnpc_inputs = \ src/capnp/c++.capnp \ src/capnp/schema.capnp \ src/capnp/stream.capnp \ src/capnp/rpc.capnp \ src/capnp/rpc-twoparty.capnp \ src/capnp/persistent.capnp capnpc_inputs = \ $(public_capnpc_inputs) \ src/capnp/compiler/lexer.capnp \ src/capnp/compiler/grammar.capnp \ src/capnp/compat/json.capnp capnpc_outputs = \ src/capnp/c++.capnp.c++ \ src/capnp/c++.capnp.h \ src/capnp/schema.capnp.c++ \ src/capnp/schema.capnp.h \ src/capnp/stream.capnp.c++ \ src/capnp/stream.capnp.h \ src/capnp/rpc.capnp.c++ \ src/capnp/rpc.capnp.h \ src/capnp/rpc-twoparty.capnp.c++ \ src/capnp/rpc-twoparty.capnp.h \ src/capnp/persistent.capnp.c++ \ src/capnp/persistent.capnp.h \ src/capnp/compat/json.capnp.h \ src/capnp/compat/json.capnp.c++ \ src/capnp/compiler/lexer.capnp.c++ \ src/capnp/compiler/lexer.capnp.h \ src/capnp/compiler/grammar.capnp.c++ \ src/capnp/compiler/grammar.capnp.h includecapnpdir = $(includedir)/capnp includecapnpcompatdir = $(includecapnpdir)/compat includekjdir = $(includedir)/kj includekjparsedir = $(includekjdir)/parse includekjstddir = $(includekjdir)/std includekjcompatdir = $(includekjdir)/compat dist_includecapnp_DATA = $(public_capnpc_inputs) dist_includecapnpcompat_DATA = src/capnp/compat/json.capnp pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(CAPNP_PKG_CONFIG_FILES) cmakeconfigdir = $(libdir)/cmake/CapnProto cmakeconfig_DATA = $(CAPNP_CMAKE_CONFIG_FILES) \ cmake/CapnProtoMacros.cmake \ cmake/CapnProtoTargets.cmake noinst_HEADERS = \ src/kj/miniposix.h \ src/kj/async-io-internal.h includekj_HEADERS = \ src/kj/common.h \ src/kj/units.h \ src/kj/memory.h \ src/kj/refcount.h \ src/kj/array.h \ src/kj/list.h \ src/kj/vector.h \ src/kj/string.h \ src/kj/string-tree.h \ src/kj/hash.h \ src/kj/table.h \ src/kj/map.h \ src/kj/encoding.h \ src/kj/exception.h \ src/kj/debug.h \ src/kj/arena.h \ src/kj/io.h \ src/kj/tuple.h \ src/kj/one-of.h \ src/kj/function.h \ src/kj/mutex.h \ src/kj/source-location.h \ src/kj/thread.h \ src/kj/threadlocal.h \ src/kj/filesystem.h \ src/kj/async-prelude.h \ src/kj/async.h \ src/kj/async-inl.h \ src/kj/time.h \ src/kj/timer.h \ src/kj/async-unix.h \ src/kj/async-win32.h \ src/kj/async-io.h \ src/kj/cidr.h \ src/kj/async-queue.h \ src/kj/main.h \ src/kj/test.h \ src/kj/win32-api-version.h \ src/kj/windows-sanity.h includekjparse_HEADERS = \ src/kj/parse/common.h \ src/kj/parse/char.h includekjstd_HEADERS = \ src/kj/std/iostream.h includekjcompat_HEADERS = \ src/kj/compat/gtest.h \ src/kj/compat/url.h \ src/kj/compat/http.h \ src/kj/compat/gzip.h \ src/kj/compat/readiness-io.h \ src/kj/compat/tls.h includecapnp_HEADERS = \ src/capnp/c++.capnp.h \ src/capnp/common.h \ src/capnp/blob.h \ src/capnp/endian.h \ src/capnp/layout.h \ src/capnp/orphan.h \ src/capnp/list.h \ src/capnp/any.h \ src/capnp/message.h \ src/capnp/capability.h \ src/capnp/membrane.h \ src/capnp/schema.capnp.h \ src/capnp/stream.capnp.h \ src/capnp/schema-lite.h \ src/capnp/schema.h \ src/capnp/schema-loader.h \ src/capnp/schema-parser.h \ src/capnp/dynamic.h \ src/capnp/pretty-print.h \ src/capnp/serialize.h \ src/capnp/serialize-async.h \ src/capnp/serialize-packed.h \ src/capnp/serialize-text.h \ src/capnp/pointer-helpers.h \ src/capnp/generated-header-support.h \ src/capnp/raw-schema.h \ src/capnp/rpc-prelude.h \ src/capnp/rpc.h \ src/capnp/rpc-twoparty.h \ src/capnp/rpc.capnp.h \ src/capnp/rpc-twoparty.capnp.h \ src/capnp/persistent.capnp.h \ src/capnp/ez-rpc.h includecapnpcompat_HEADERS = \ src/capnp/compat/json.h \ src/capnp/compat/json.capnp.h \ src/capnp/compat/std-iterator.h \ src/capnp/compat/websocket-rpc.h if BUILD_KJ_TLS MAYBE_KJ_TLS_LA=libkj-tls.la MAYBE_KJ_TLS_TESTS= \ src/kj/compat/readiness-io-test.c++ \ src/kj/compat/tls-test.c++ else MAYBE_KJ_TLS_LA= MAYBE_KJ_TLS_TESTS= endif if BUILD_KJ_GZIP MAYBE_KJ_GZIP_LA=libkj-gzip.la MAYBE_KJ_GZIP_TESTS= \ src/kj/compat/gzip-test.c++ else MAYBE_KJ_TLS_LA= MAYBE_KJ_TLS_TESTS= endif if LITE_MODE lib_LTLIBRARIES = libkj.la libkj-test.la libcapnp.la else lib_LTLIBRARIES = libkj.la libkj-test.la libkj-async.la libkj-http.la $(MAYBE_KJ_TLS_LA) $(MAYBE_KJ_GZIP_LA) libcapnp.la libcapnp-rpc.la libcapnp-json.la libcapnp-websocket.la libcapnpc.la endif libkj_la_LIBADD = $(PTHREAD_LIBS) libkj_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_la_SOURCES= \ src/kj/cidr.c++ \ src/kj/common.c++ \ src/kj/units.c++ \ src/kj/memory.c++ \ src/kj/refcount.c++ \ src/kj/array.c++ \ src/kj/list.c++ \ src/kj/string.c++ \ src/kj/string-tree.c++ \ src/kj/source-location.c++ \ src/kj/hash.c++ \ src/kj/table.c++ \ src/kj/encoding.c++ \ src/kj/exception.c++ \ src/kj/debug.c++ \ src/kj/arena.c++ \ src/kj/io.c++ \ src/kj/mutex.c++ \ src/kj/thread.c++ \ src/kj/time.c++ \ src/kj/filesystem.c++ \ src/kj/filesystem-disk-unix.c++ \ src/kj/filesystem-disk-win32.c++ \ src/kj/test-helpers.c++ \ src/kj/main.c++ \ src/kj/parse/char.c++ libkj_test_la_LIBADD = libkj.la $(PTHREAD_LIBS) libkj_test_la_LDFLAGS = -release $(VERSION) -no-undefined libkj_test_la_SOURCES = src/kj/test.c++ if !LITE_MODE libkj_async_la_LIBADD = libkj.la $(ASYNC_LIBS) $(PTHREAD_LIBS) libkj_async_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_async_la_SOURCES= \ src/kj/async.c++ \ src/kj/async-unix.c++ \ src/kj/async-win32.c++ \ src/kj/async-io.c++ \ src/kj/async-io-unix.c++ \ src/kj/async-io-win32.c++ \ src/kj/timer.c++ if BUILD_KJ_GZIP libkj_http_la_LIBADD = libkj-async.la libkj.la -lz $(ASYNC_LIBS) $(PTHREAD_LIBS) libkj_http_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_http_la_SOURCES= \ src/kj/compat/url.c++ \ src/kj/compat/http.c++ else libkj_http_la_LIBADD = libkj-async.la libkj.la $(ASYNC_LIBS) $(PTHREAD_LIBS) libkj_http_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_http_la_SOURCES= \ src/kj/compat/url.c++ \ src/kj/compat/http.c++ endif libkj_tls_la_LIBADD = libkj-async.la libkj.la -lssl -lcrypto $(ASYNC_LIBS) $(PTHREAD_LIBS) libkj_tls_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_tls_la_SOURCES= \ src/kj/compat/readiness-io.c++ \ src/kj/compat/tls.c++ libkj_gzip_la_LIBADD = libkj-async.la libkj.la -lz $(ASYNC_LIBS) $(PTHREAD_LIBS) libkj_gzip_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libkj_gzip_la_SOURCES= \ src/kj/compat/gzip.c++ endif !LITE_MODE if !LITE_MODE heavy_sources = \ src/capnp/schema.c++ \ src/capnp/schema-loader.c++ \ src/capnp/dynamic.c++ \ src/capnp/stringify.c++ endif !LITE_MODE libcapnp_la_LIBADD = libkj.la $(PTHREAD_LIBS) libcapnp_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libcapnp_la_SOURCES= \ src/capnp/c++.capnp.c++ \ src/capnp/blob.c++ \ src/capnp/arena.h \ src/capnp/arena.c++ \ src/capnp/layout.c++ \ src/capnp/list.c++ \ src/capnp/any.c++ \ src/capnp/message.c++ \ src/capnp/schema.capnp.c++ \ src/capnp/stream.capnp.c++ \ src/capnp/serialize.c++ \ src/capnp/serialize-packed.c++ \ $(heavy_sources) if !LITE_MODE libcapnp_rpc_la_LIBADD = libcapnp.la libkj-async.la libkj.la $(ASYNC_LIBS) $(PTHREAD_LIBS) libcapnp_rpc_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libcapnp_rpc_la_SOURCES= \ src/capnp/serialize-async.c++ \ src/capnp/capability.c++ \ src/capnp/membrane.c++ \ src/capnp/dynamic-capability.c++ \ src/capnp/rpc.c++ \ src/capnp/rpc.capnp.c++ \ src/capnp/rpc-twoparty.c++ \ src/capnp/rpc-twoparty.capnp.c++ \ src/capnp/persistent.capnp.c++ \ src/capnp/ez-rpc.c++ libcapnp_json_la_LIBADD = libcapnp.la libkj.la $(PTHREAD_LIBS) libcapnp_json_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libcapnp_json_la_SOURCES= \ src/capnp/compat/json.c++ \ src/capnp/compat/json.capnp.c++ libcapnp_websocket_la_LIBADD = libcapnp.la libcapnp-rpc.la libkj.la libkj-async.la libkj-http.la $(PTHREAD_LIBS) libcapnp_websocket_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libcapnp_websocket_la_SOURCES= \ src/capnp/compat/websocket-rpc.c++ libcapnpc_la_LIBADD = libcapnp.la libkj.la $(PTHREAD_LIBS) libcapnpc_la_LDFLAGS = -release $(SO_VERSION) -no-undefined libcapnpc_la_SOURCES= \ src/capnp/compiler/type-id.h \ src/capnp/compiler/type-id.c++ \ src/capnp/compiler/error-reporter.h \ src/capnp/compiler/error-reporter.c++ \ src/capnp/compiler/lexer.capnp.h \ src/capnp/compiler/lexer.capnp.c++ \ src/capnp/compiler/lexer.h \ src/capnp/compiler/lexer.c++ \ src/capnp/compiler/grammar.capnp.h \ src/capnp/compiler/grammar.capnp.c++ \ src/capnp/compiler/parser.h \ src/capnp/compiler/parser.c++ \ src/capnp/compiler/resolver.h \ src/capnp/compiler/generics.h \ src/capnp/compiler/generics.c++ \ src/capnp/compiler/node-translator.h \ src/capnp/compiler/node-translator.c++ \ src/capnp/compiler/compiler.h \ src/capnp/compiler/compiler.c++ \ src/capnp/schema-parser.c++ \ src/capnp/serialize-text.c++ bin_PROGRAMS = capnp capnpc-capnp capnpc-c++ capnp_LDADD = libcapnpc.la libcapnp-json.la libcapnp.la libkj.la $(PTHREAD_LIBS) capnp_SOURCES = \ src/capnp/compiler/module-loader.h \ src/capnp/compiler/module-loader.c++ \ src/capnp/compiler/capnp.c++ capnpc_capnp_LDADD = libcapnp.la libkj.la $(PTHREAD_LIBS) capnpc_capnp_SOURCES = src/capnp/compiler/capnpc-capnp.c++ capnpc_c___LDADD = libcapnp.la libkj.la $(PTHREAD_LIBS) capnpc_c___SOURCES = src/capnp/compiler/capnpc-c++.c++ # Symlink capnpc -> capnp. The capnp binary will behave like the old capnpc # binary (i.e. like "capnp compile") when invoked via this symlink. # # Also attempt to run ldconfig, because otherwise users get confused. If # it fails (e.g. because the platform doesn't have it, or because the # user doesn't have root privileges), don't worry about it. # # We need to specify the path for OpenBSD. install-exec-hook: ln -sf capnp $(DESTDIR)$(bindir)/capnpc if [ `uname` == 'OpenBSD' ]; then \ (ldconfig /usr/local/lib /usr/lib /usr/X11R6/lib > /dev/null 2>&1 || true); \ else \ ldconfig < /dev/null > /dev/null 2>&1 || true; \ fi uninstall-hook: rm -f $(DESTDIR)$(bindir)/capnpc else LITE_MODE install-exec-hook: ldconfig < /dev/null > /dev/null 2>&1 || true endif LITE_MODE # Source files intentionally not included in the dist at this time: # src/capnp/serialize-snappy* # src/capnp/benchmark/... # src/capnp/compiler/... # Tests ============================================================== test_capnpc_inputs = \ src/capnp/test.capnp \ src/capnp/test-import.capnp \ src/capnp/test-import2.capnp \ src/capnp/compat/json-test.capnp test_capnpc_outputs = \ src/capnp/test.capnp.c++ \ src/capnp/test.capnp.h \ src/capnp/test-import.capnp.c++ \ src/capnp/test-import.capnp.h \ src/capnp/test-import2.capnp.c++ \ src/capnp/test-import2.capnp.h \ src/capnp/compat/json-test.capnp.c++ \ src/capnp/compat/json-test.capnp.h if USE_EXTERNAL_CAPNP test_capnpc_middleman: $(test_capnpc_inputs) @$(MKDIR_P) src $(CAPNP) compile --src-prefix=$(srcdir)/src -o$(CAPNPC_CXX):src -I$(srcdir)/src $$(for FILE in $(test_capnpc_inputs); do echo $(srcdir)/$$FILE; done) touch test_capnpc_middleman else test_capnpc_middleman: capnp$(EXEEXT) capnpc-c++$(EXEEXT) $(test_capnpc_inputs) @$(MKDIR_P) src ./capnp$(EXEEXT) compile --src-prefix=$(srcdir)/src -o./capnpc-c++$(EXEEXT):src -I$(srcdir)/src $$(for FILE in $(test_capnpc_inputs); do echo $(srcdir)/$$FILE; done) touch test_capnpc_middleman endif $(test_capnpc_outputs): test_capnpc_middleman BUILT_SOURCES = $(test_capnpc_outputs) check_LIBRARIES = libcapnp-test.a libcapnp_test_a_SOURCES = \ src/capnp/test-util.c++ \ src/capnp/test-util.h nodist_libcapnp_test_a_SOURCES = $(test_capnpc_outputs) if LITE_MODE check_PROGRAMS = capnp-test compiler_tests = capnp_test_LDADD = libcapnp-test.a libcapnp.la libkj-test.la libkj.la else !LITE_MODE check_PROGRAMS = capnp-test capnp-evolution-test capnp-afl-testcase if HAS_FUZZING_ENGINE check_PROGRAMS += capnp-llvm-fuzzer-testcase endif heavy_tests = \ src/kj/async-test.c++ \ src/kj/async-xthread-test.c++ \ src/kj/async-coroutine-test.c++ \ src/kj/async-unix-test.c++ \ src/kj/async-unix-xthread-test.c++ \ src/kj/async-win32-test.c++ \ src/kj/async-win32-xthread-test.c++ \ src/kj/async-io-test.c++ \ src/kj/async-queue-test.c++ \ src/kj/parse/common-test.c++ \ src/kj/parse/char-test.c++ \ src/kj/std/iostream-test.c++ \ src/kj/compat/url-test.c++ \ src/kj/compat/http-test.c++ \ $(MAYBE_KJ_GZIP_TESTS) \ $(MAYBE_KJ_TLS_TESTS) \ src/capnp/canonicalize-test.c++ \ src/capnp/capability-test.c++ \ src/capnp/membrane-test.c++ \ src/capnp/schema-test.c++ \ src/capnp/schema-loader-test.c++ \ src/capnp/schema-parser-test.c++ \ src/capnp/dynamic-test.c++ \ src/capnp/stringify-test.c++ \ src/capnp/serialize-async-test.c++ \ src/capnp/serialize-text-test.c++ \ src/capnp/rpc-test.c++ \ src/capnp/rpc-twoparty-test.c++ \ src/capnp/ez-rpc-test.c++ \ src/capnp/compat/json-test.c++ \ src/capnp/compat/websocket-rpc-test.c++ \ src/capnp/compiler/lexer-test.c++ \ src/capnp/compiler/type-id-test.c++ capnp_test_LDADD = \ libcapnp-test.a \ libcapnpc.la \ libcapnp-rpc.la \ libcapnp-websocket.la \ libcapnp-json.la \ libcapnp.la \ libkj-http.la \ $(MAYBE_KJ_GZIP_LA) \ $(MAYBE_KJ_TLS_LA) \ libkj-async.la \ libkj-test.la \ libkj.la \ $(ASYNC_LIBS) \ $(PTHREAD_LIBS) endif !LITE_MODE capnp_test_CPPFLAGS = -Wno-deprecated-declarations capnp_test_SOURCES = \ src/kj/common-test.c++ \ src/kj/memory-test.c++ \ src/kj/refcount-test.c++ \ src/kj/array-test.c++ \ src/kj/list-test.c++ \ src/kj/string-test.c++ \ src/kj/string-tree-test.c++ \ src/kj/table-test.c++ \ src/kj/map-test.c++ \ src/kj/encoding-test.c++ \ src/kj/exception-test.c++ \ src/kj/debug-test.c++ \ src/kj/arena-test.c++ \ src/kj/units-test.c++ \ src/kj/tuple-test.c++ \ src/kj/one-of-test.c++ \ src/kj/function-test.c++ \ src/kj/io-test.c++ \ src/kj/mutex-test.c++ \ src/kj/time-test.c++ \ src/kj/threadlocal-test.c++ \ src/kj/filesystem-test.c++ \ src/kj/filesystem-disk-test.c++ \ src/kj/test-test.c++ \ src/capnp/common-test.c++ \ src/capnp/blob-test.c++ \ src/capnp/endian-test.c++ \ src/capnp/endian-fallback-test.c++ \ src/capnp/endian-reverse-test.c++ \ src/capnp/layout-test.c++ \ src/capnp/any-test.c++ \ src/capnp/message-test.c++ \ src/capnp/encoding-test.c++ \ src/capnp/orphan-test.c++ \ src/capnp/serialize-test.c++ \ src/capnp/serialize-packed-test.c++ \ src/capnp/fuzz-test.c++ \ $(heavy_tests) if !LITE_MODE capnp_evolution_test_LDADD = libcapnpc.la libcapnp.la libkj.la capnp_evolution_test_SOURCES = src/capnp/compiler/evolution-test.c++ capnp_afl_testcase_LDADD = libcapnp-test.a libcapnp-rpc.la libcapnp.la libkj.la libkj-async.la capnp_afl_testcase_SOURCES = src/capnp/afl-testcase.c++ if HAS_FUZZING_ENGINE capnp_llvm_fuzzer_testcase_LDADD = libcapnp-test.a libcapnp-rpc.la libcapnp.la libkj.la libkj-async.la capnp_llvm_fuzzer_testcase_SOURCES = src/capnp/llvm-fuzzer-testcase.c++ capnp_llvm_fuzzer_testcase_LDFLAGS = $(LIB_FUZZING_ENGINE) endif endif !LITE_MODE if LITE_MODE TESTS = capnp-test else !LITE_MODE TESTS = capnp-test capnp-evolution-test src/capnp/compiler/capnp-test.sh endif !LITE_MODE capnproto-c++-1.1.0/README.txt0000644000175000017500000000213214527152321016440 0ustar00kentonkenton00000000000000Cap'n Proto - Insanely Fast Data Serialization Format Copyright 2013-2015 Sandstorm Development Group, Inc. https://capnproto.org Cap'n Proto is an insanely fast data interchange format and capability-based RPC system. Think JSON, except binary. Or think of Google's Protocol Buffers (http://protobuf.googlecode.com), except faster. In fact, in benchmarks, Cap'n Proto is INFINITY TIMES faster than Protocol Buffers. Full installation and usage instructions and other documentation are maintained on the Cap'n Proto web site: http://kentonv.github.io/capnproto/install.html WARNING: Cap'n Proto requires a modern compiler. See the above link for detailed requirements. To build and install (from a release package), simply do: ./configure make -j4 check sudo make install The -j4 allows the build to use up to four processor cores instead of one. You can increase this number if you have more cores. Specifying "check" says to run tests in addition to building. This can be omitted to make the build slightly faster, but running tests and reporting failures back to the developers helps us out! capnproto-c++-1.1.0/build-aux/0000755000175000017500000000000014731562205016641 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/build-aux/install-sh0000755000175000017500000003577614731562165020674 0ustar00kentonkenton00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: capnproto-c++-1.1.0/build-aux/config.guess0000755000175000017500000014051214731562165021171 0ustar00kentonkenton00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-01-09' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # Just in case it came from the environment. GUESS= # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case $UNAME_SYSTEM in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=$UNAME_MACHINE_ARCH-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case $UNAME_VERSION in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case $ALPHA_CPU_TYPE in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; sun4*:SunOS:*:*) case `/usr/bin/arch -k` in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case `/bin/arch` in sun3) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` case $UNAME_MACHINE in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case $sc_cpu_version in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case $sc_kernel_bits in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI=${LIBC}x32 fi fi GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. GUESS=i386-sequent-sysv4 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; x86_64:Haiku:*:*) GUESS=x86_64-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "${cputype-}" = 386; then UNAME_MACHINE=i386 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: capnproto-c++-1.1.0/build-aux/config.sub0000755000175000017500000010511614731562165020635 0ustar00kentonkenton00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-01-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ | linux-musl* | linux-relibc* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: capnproto-c++-1.1.0/build-aux/missing0000755000175000017500000001533614731562165020255 0ustar00kentonkenton00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2021 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: capnproto-c++-1.1.0/build-aux/compile0000755000175000017500000001635014731562165020231 0ustar00kentonkenton00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: capnproto-c++-1.1.0/build-aux/depcomp0000755000175000017500000005602014731562165020226 0ustar00kentonkenton00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: capnproto-c++-1.1.0/build-aux/ltmain.sh0000755000175000017500000121240114731562164020471 0ustar00kentonkenton00000000000000#! /usr/bin/env sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2019-02-19.15 # libtool (GNU libtool) 2.4.7 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.7 Debian-2.4.7-7~deb12u1" package_revision=2.4.7 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2019-02-19.15; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2004-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # These NLS vars are set unconditionally (bootstrap issue #24). Unset those # in case the environment reset is needed later and the $save_* variant is not # defined (see the code above). LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # func_unset VAR # -------------- # Portably unset VAR. # In some shells, an 'unset VAR' statement leaves a non-zero return # status if VAR is already unset, which might be problematic if the # statement is used at the end of a function (thus poisoning its return # value) or when 'set -e' is active (causing even a spurious abort of # the script in this case). func_unset () { { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } } # Make sure CDPATH doesn't cause `cd` commands to output the target dir. func_unset CDPATH # Make sure ${,E,F}GREP behave sanely. func_unset GREP_OPTIONS ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" # require_check_ifs_backslash # --------------------------- # Check if we can use backslash as IFS='\' separator, and set # $check_ifs_backshlash_broken to ':' or 'false'. require_check_ifs_backslash=func_require_check_ifs_backslash func_require_check_ifs_backslash () { _G_save_IFS=$IFS IFS='\' _G_check_ifs_backshlash='a\\b' for _G_i in $_G_check_ifs_backshlash do case $_G_i in a) check_ifs_backshlash_broken=false ;; '') break ;; *) check_ifs_backshlash_broken=: break ;; esac done IFS=$_G_save_IFS require_check_ifs_backslash=: } ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. if test -z "$_G_HAVE_PLUSEQ_OP" && \ __PLUSEQ_TEST="a" && \ __PLUSEQ_TEST+=" b" 2>/dev/null && \ test "a b" = "$__PLUSEQ_TEST"; then _G_HAVE_PLUSEQ_OP=yes fi if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1+=\\ \$func_quote_arg_result" }' else func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1=\$$1\\ \$func_quote_arg_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_portable EVAL ARG # ---------------------------- # Internal function to portably implement func_quote_arg. Note that we still # keep attention to performance here so we as much as possible try to avoid # calling sed binary (so far O(N) complexity as long as func_append is O(1)). func_quote_portable () { $debug_cmd $require_check_ifs_backslash func_quote_portable_result=$2 # one-time-loop (easy break) while true do if $1; then func_quote_portable_result=`$ECHO "$2" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` break fi # Quote for eval. case $func_quote_portable_result in *[\\\`\"\$]*) # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string # contains the shell wildcard characters. case $check_ifs_backshlash_broken$func_quote_portable_result in :*|*[\[\*\?]*) func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ | $SED "$sed_quote_subst"` break ;; esac func_quote_portable_old_IFS=$IFS for _G_char in '\' '`' '"' '$' do # STATE($1) PREV($2) SEPARATOR($3) set start "" "" func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy IFS=$_G_char for _G_part in $func_quote_portable_result do case $1 in quote) func_append func_quote_portable_result "$3$2" set quote "$_G_part" "\\$_G_char" ;; start) set first "" "" func_quote_portable_result= ;; first) set quote "$_G_part" "" ;; esac done done IFS=$func_quote_portable_old_IFS ;; *) ;; esac break done func_quote_portable_unquoted_result=$func_quote_portable_result case $func_quote_portable_result in # double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # many bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_portable_result=\"$func_quote_portable_result\" ;; esac } # func_quotefast_eval ARG # ----------------------- # Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', # but optimized for speed. Result is stored in $func_quotefast_eval. if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then printf -v _GL_test_printf_tilde %q '~' if test '\~' = "$_GL_test_printf_tilde"; then func_quotefast_eval () { printf -v func_quotefast_eval_result %q "$1" } else # Broken older Bash implementations. Make those faster too if possible. func_quotefast_eval () { case $1 in '~'*) func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result ;; *) printf -v func_quotefast_eval_result %q "$1" ;; esac } fi else func_quotefast_eval () { func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result } fi # func_quote_arg MODEs ARG # ------------------------ # Quote one ARG to be evaled later. MODEs argument may contain zero or more # specifiers listed below separated by ',' character. This function returns two # values: # i) func_quote_arg_result # double-quoted (when needed), suitable for a subsequent eval # ii) func_quote_arg_unquoted_result # has all characters that are still active within double # quotes backslashified. Available only if 'unquoted' is specified. # # Available modes: # ---------------- # 'eval' (default) # - escape shell special characters # 'expand' # - the same as 'eval'; but do not quote variable references # 'pretty' # - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might # be used later in func_quote to get output like: 'echo "a b"' instead # of 'echo a\ b'. This is slower than default on some shells. # 'unquoted' # - produce also $func_quote_arg_unquoted_result which does not contain # wrapping double-quotes. # # Examples for 'func_quote_arg pretty,unquoted string': # # string | *_result | *_unquoted_result # ------------+-----------------------+------------------- # " | \" | \" # a b | "a b" | a b # "a b" | "\"a b\"" | \"a b\" # * | "*" | * # z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" # # Examples for 'func_quote_arg pretty,unquoted,expand string': # # string | *_result | *_unquoted_result # --------------+---------------------+-------------------- # z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" func_quote_arg () { _G_quote_expand=false case ,$1, in *,expand,*) _G_quote_expand=: ;; esac case ,$1, in *,pretty,*|*,expand,*|*,unquoted,*) func_quote_portable $_G_quote_expand "$2" func_quote_arg_result=$func_quote_portable_result func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result ;; *) # Faster quote-for-eval for some shells. func_quotefast_eval "$2" func_quote_arg_result=$func_quotefast_eval_result ;; esac } # func_quote MODEs ARGs... # ------------------------ # Quote all ARGs to be evaled later and join them into single command. See # func_quote_arg's description for more info. func_quote () { $debug_cmd _G_func_quote_mode=$1 ; shift func_quote_result= while test 0 -lt $#; do func_quote_arg "$_G_func_quote_mode" "$1" if test -n "$func_quote_result"; then func_append func_quote_result " $func_quote_arg_result" else func_append func_quote_result "$func_quote_arg_result" fi shift done } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_arg pretty,expand "$_G_cmd" eval "func_notquiet $func_quote_arg_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_arg expand,pretty "$_G_cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2010-2019, 2021 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 2 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # # Set a version string for this script. scriptversion=2019-02-19.15; # UTC ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# Copyright'. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug in processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # in the main code. A hook is just a list of function names that can be # run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of hook functions to be called by # FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_propagate_result FUNC_NAME_A FUNC_NAME_B # --------------------------------------------- # If the *_result variable of FUNC_NAME_A _is set_, assign its value to # *_result variable of FUNC_NAME_B. func_propagate_result () { $debug_cmd func_propagate_result_result=: if eval "test \"\${${1}_result+set}\" = set" then eval "${2}_result=\$${1}_result" else func_propagate_result_result=false fi } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It's assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd _G_rc_run_hooks=false case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook functions." ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do func_unset "${_G_hook}_result" eval $_G_hook '${1+"$@"}' func_propagate_result $_G_hook func_run_hooks if $func_propagate_result_result; then eval set dummy "$func_run_hooks_result"; shift fi done } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list from your hook function. You may remove # or edit any options that you action, and then pass back the remaining # unprocessed options in '_result', escaped # suitably for 'eval'. # # The '_result' variable is automatically unset # before your hook gets called; for best performance, only set the # *_result variable when necessary (i.e. don't call the 'func_quote' # function unnecessarily because it can be an expensive operation on some # machines). # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). Leave # # my_options_prep_result variable intact. # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # Note that, for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: # args_changed=: # ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@" in case we need it later, # # if $args_changed was set to 'true'. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # # Only call 'func_quote' here if we processed at least one argument. # if $args_changed; then # func_quote eval ${1+"$@"} # my_silent_option_result=$func_quote_result # fi # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # } # func_add_hook func_validate_options my_option_validation # # You'll also need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd func_run_hooks func_options ${1+"$@"} func_propagate_result func_run_hooks func_options_finish } # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd _G_options_quoted=false for my_func in options_prep parse_options validate_options options_finish do func_unset func_${my_func}_result func_unset func_run_hooks_result eval func_$my_func '${1+"$@"}' func_propagate_result func_$my_func func_options if $func_propagate_result_result; then eval set dummy "$func_options_result"; shift _G_options_quoted=: fi done $_G_options_quoted || { # As we (func_options) are top-level options-parser function and # nobody quoted "$@" for us yet, we need to do it explicitly for # caller. func_quote eval ${1+"$@"} func_options_result=$func_quote_result } } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} func_propagate_result func_run_hooks func_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd _G_parse_options_requote=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} func_propagate_result func_run_hooks func_parse_options if $func_propagate_result_result; then eval set dummy "$func_parse_options_result"; shift # Even though we may have changed "$@", we passed the "$@" array # down into the hook and it quoted it for us (because we are in # this if-branch). No need to quote it again. _G_parse_options_requote=false fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break # We expect that one of the options parsed in this function matches # and thus we remove _G_opt from "$@" and need to re-quote. _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" >&2 $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) if test $# = 0 && func_missing_arg $_G_opt; then _G_parse_options_requote=: break fi case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) _G_parse_options_requote=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac if $_G_match_parse_options; then _G_parse_options_requote=: fi done if $_G_parse_options_requote; then # save modified positional parameters for caller func_quote eval ${1+"$@"} func_parse_options_result=$func_quote_result fi } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} func_propagate_result func_run_hooks func_validate_options # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables # after splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} if test "x$func_split_equals_lhs" = "x$1"; then func_split_equals_rhs= fi }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs=" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. # The version message is extracted from the calling file's header # comments, with leading '# ' stripped: # 1. First display the progname and version # 2. Followed by the header comment line matching /^# Written by / # 3. Then a blank line followed by the first following line matching # /^# Copyright / # 4. Immediately followed by any lines between the previous matches, # except lines preceding the intervening completely blank line. # For example, see the header comments of this file. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /^# Written by /!b s|^# ||; p; n :fwd2blnk /./ { n b fwd2blnk } p; n :holdwrnt s|^# || s|^# *$|| /^Copyright /!{ /./H n b holdwrnt } s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| G s|\(\n\)\n*|\1|g p; q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.7' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname $scriptversion Debian-2.4.7-7~deb12u1 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= _G_rc_lt_options_prep=: _G_rc_lt_options_prep=: # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote eval ${1+"$@"} libtool_options_prep_result=$func_quote_result fi } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"} ; shift _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote eval ${1+"$@"} libtool_parse_options_result=$func_quote_result fi } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote eval ${1+"$@"} libtool_validate_options_result=$func_quote_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_arg pretty "$libobj" test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_arg pretty "$srcfile" qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG -Xcompiler FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wa,FLAG -Xassembler FLAG pass linker-specific FLAG directly to the assembler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_arg pretty "$nonopt" install_prog="$func_quote_arg_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_arg pretty "$arg" func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_arg pretty "$arg" func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then func_quote_arg pretty "$arg2" fi func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_arg pretty "$install_override_mode" func_append install_shared_prog " -m $func_quote_arg_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_arg expand,pretty "$relink_command" eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" func_quote_arg pretty "$ECHO" qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_arg pretty,unquoted "$arg" qarg=$func_quote_arg_unquoted_result func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xassembler) func_append compiler_flags " -Xassembler $qarg" prev= func_append compile_command " -Xassembler $qarg" func_append finalize_command " -Xassembler $qarg" continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199. -pthread) case $host in *solaris2*) ;; *) case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac ;; esac continue ;; -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $func_quote_arg_result" func_append compiler_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $wl$func_quote_arg_result" func_append compiler_flags " $wl$func_quote_arg_result" func_append linker_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xassembler) prev=xassembler continue ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC # -static-* direct GCC to link specific libraries statically # -fcilkplus Cilk Plus language extension features for C/C++ # -Wa,* Pass flags directly to the assembler -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus|-Wa,*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_arg pretty "$arg" arg=$func_quote_arg_result fi ;; # Some other compiler flag. -* | +*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf | midnightbsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty "$var_value" relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done func_quote eval cd "`pwd`" func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty,unquoted "$var_value" relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" fi done # Quote the link command for shipping. func_quote eval cd "`pwd`" relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" func_quote_arg pretty,unquoted "$relink_command" relink_command=$func_quote_arg_unquoted_result if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: capnproto-c++-1.1.0/m4/0000755000175000017500000000000014731562204015266 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/m4/acx_pthread.m40000644000175000017500000003523014712011043020002 0ustar00kentonkenton00000000000000# This file was copied to Cap'n Proto from the Protocol Buffers distribution, # version 2.3.0. # This was retrieved from # http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi # See also (perhaps for new versions?) # http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi # # We've rewritten the inconsistency check code (from avahi), to work # more broadly. In particular, it no longer assumes ld accepts -zdefs. # This caused a restructing of the code, but the functionality has only # changed a little. dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl dnl @summary figure out how to build C programs using POSIX threads dnl dnl This macro figures out how to build C programs using POSIX threads. dnl It sets the PTHREAD_LIBS output variable to the threads library and dnl linker flags, and the PTHREAD_CFLAGS output variable to any special dnl C compiler flags that are needed. (The user can also force certain dnl compiler flags/libs to be tested by setting these environment dnl variables.) dnl dnl Also sets PTHREAD_CC to any special C compiler that is needed for dnl multi-threaded programs (defaults to the value of CC otherwise). dnl (This is necessary on AIX to use the special cc_r compiler alias.) dnl dnl NOTE: You are assumed to not only compile your program with these dnl flags, but also link it with them as well. e.g. you should link dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS dnl $LIBS dnl dnl If you are only building threads programs, you may wish to use dnl these variables in your default LIBS, CFLAGS, and CC: dnl dnl LIBS="$PTHREAD_LIBS $LIBS" dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" dnl CC="$PTHREAD_CC" dnl dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). dnl dnl ACTION-IF-FOUND is a list of shell commands to run if a threads dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the dnl default action will define HAVE_PTHREAD. dnl dnl Please let the authors know if this macro fails on any platform, or dnl if you have any other suggestions or comments. This macro was based dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. dnl We are also grateful for the helpful feedback of numerous users. dnl dnl @category InstalledPackages dnl @author Steven G. Johnson dnl @version 2006-05-29 dnl @license GPLWithACException dnl dnl Checks for GCC shared/pthread inconsistency based on work by dnl Marcin Owsiany AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi # The next part tries to detect GCC inconsistency with -shared on some # architectures and systems. The problem is that in certain # configurations, when -shared is specified, GCC "forgets" to # internally use various flags which are still necessary. # # Prepare the flags # save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" # Try with the flags determined by the earlier checks. # # -Wl,-z,defs forces link-time symbol resolution, so that the # linking checks with -shared actually have any value # # FIXME: -fPIC is required for -shared on many architectures, # so we specify it here, but the right way would probably be to # properly detect whether it is actually required. CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CC="$PTHREAD_CC" # In order not to create several levels of indentation, we test # the value of "$done" until we find the cure or run out of ideas. done="no" # First, make sure the CFLAGS we added are actually accepted by our # compiler. If not (and OS X's ld, for instance, does not accept -z), # then we can't do this test. if test x"$done" = xno; then AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies]) AC_TRY_LINK(,, , [done=yes]) if test "x$done" = xyes ; then AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) fi fi if test x"$done" = xno; then AC_MSG_CHECKING([whether -pthread is sufficient with -shared]) AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi # # Linux gcc on some architectures such as mips/mipsel forgets # about -lpthread # if test x"$done" = xno; then AC_MSG_CHECKING([whether -lpthread fixes that]) LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" else AC_MSG_RESULT([no]) fi fi # # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc # if test x"$done" = xno; then AC_MSG_CHECKING([whether -lc_r fixes that]) LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" else AC_MSG_RESULT([no]) fi fi if test x"$done" = xno; then # OK, we have run out of ideas AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries]) # so it's not safe to assume that we may use pthreads acx_pthread_ok=no fi CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" else PTHREAD_CC="$CC" fi if test "x$acx_pthread_ok" = xyes; then # One more check: If we chose to use a compiler flag like -pthread but it is combined with # -nostdlib then the compiler won't implicitly link against libpthread. This can happen # in particular when using some versions of libtool on some distros. See: # https://bugzilla.redhat.com/show_bug.cgi?id=661333 save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="-nostdlib $PTHREAD_LIBS $LIBS -lc" CC="$PTHREAD_CC" AC_MSG_CHECKING([whether pthread flag is sufficient with -nostdlib]) AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([whether adding -lpthread fixes that]) LIBS="-nostdlib $PTHREAD_LIBS -lpthread $save_LIBS -lc" AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [ AC_MSG_RESULT([yes]) PTHREAD_LIBS="$PTHREAD_LIBS -lpthread" ], [AC_MSG_RESULT([no])]) ]) CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD capnproto-c++-1.1.0/m4/ax_cxx_compile_stdcxx_14.m40000644000175000017500000001561514712011043022430 0ustar00kentonkenton00000000000000# ============================================================================ # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # Additionally modified to detect -stdlib by Kenton Varda. # Further modified for C++14 by Kenton Varda. # ============================================================================ # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_14([ext|noext]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++14 # standard; if necessary, add switches to CXXFLAGS to enable support. # Errors out if no mode that supports C++14 baseline syntax can be found. # The argument, if specified, indicates whether you insist on an extended # mode (e.g. -std=gnu++14) or a strict conformance mode (e.g. -std=c++14). # If neither is specified, you get whatever works, with preference for an # extended mode. # # Additionally, check if the standard library supports C++11. If not, # try adding -stdlib=libc++ to see if that fixes it. This is needed e.g. # on Mac OSX 10.8, which ships with a very old libstdc++ but a relatively # new libc++. # # Both flags are actually added to CXX rather than CXXFLAGS to work around # a bug in libtool: -stdlib is stripped from CXXFLAGS when linking dynamic # libraries because it is not recognized. A patch was committed to mainline # libtool in February 2012 but as of June 2013 there has not yet been a # release containing this patch. # http://git.savannah.gnu.org/gitweb/?p=libtool.git;a=commit;h=c0c49f289f22ae670066657c60905986da3b555f # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Kenton Varda # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 1 m4_define([_AX_CXX_COMPILE_STDCXX_14_testbody], [[ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); // GCC 4.7 introduced __float128 and makes reference to it in type_traits. // Clang doesn't implement it, so produces an error. Using -std=c++11 // instead of -std=gnu++11 works around the problem. But on some // platforms we need -std=gnu++11. So we want to make sure the test of // -std=gnu++11 fails only where this problem is present, and we hope that // -std=c++11 is always an acceptable fallback in these cases. Complicating // matters, though, is that we don't want to fail here if the platform is // completely missing a C++11 standard library, because we want to probe that // in a later test. It happens, though, that Clang allows us to check // whether a header exists at all before we include it. // // So, if we detect that __has_include is available (which it is on Clang), // and we use it to detect that (a C++11 header) exists, then // we go ahead and #include it to see if it breaks. In all other cases, we // don't #include it at all. #ifdef __has_include #if __has_include() #include #endif #endif // C++14 stuff auto deduceReturnType(int i) { return i; } auto genericLambda = [](auto x, auto y) { return x + y; }; auto captureExpressions = [x = 123]() { return x; }; // Avoid unused variable warnings. int foo() { return genericLambda(1, 2) + captureExpressions(); } ]]) m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody_lib], [ #include #include #include #include ]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [dnl m4_if([$1], [], [], [$1], [ext], [], [$1], [noext], [], [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_14])])dnl AC_LANG_ASSERT([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++14 features by default, ax_cv_cxx_compile_cxx14, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_14_testbody])], [ax_cv_cxx_compile_cxx14=yes], [ax_cv_cxx_compile_cxx14=no])]) if test x$ax_cv_cxx_compile_cxx14 = xyes; then ac_success=yes fi m4_if([$1], [noext], [], [dnl if test x$ac_success = xno; then for switch in -std=gnu++14 -std=gnu++1y; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx14_$switch]) AC_CACHE_CHECK(whether $CXX supports C++14 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_14_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" ac_success=yes break fi done fi]) m4_if([$1], [ext], [], [dnl if test x$ac_success = xno; then for switch in -std=c++14 -std=c++1y; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx14_$switch]) AC_CACHE_CHECK(whether $CXX supports C++14 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_14_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" ac_success=yes break fi done fi]) if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++14 language features is required.]) else ac_success=no AC_CACHE_CHECK(whether $CXX supports C++11 library features by default, ax_cv_cxx_compile_cxx11_lib, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody_lib])], [ax_cv_cxx_compile_cxx11_lib=yes], [ax_cv_cxx_compile_cxx11_lib=no]) ]) if test x$ax_cv_cxx_compile_cxx11_lib = xyes; then ac_success=yes else # Try with -stdlib=libc++ AC_CACHE_CHECK(whether $CXX supports C++11 library features with -stdlib=libc++, ax_cv_cxx_compile_cxx11_lib_libcxx, [ac_save_CXX="$CXX" CXX="$CXX -stdlib=libc++" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody_lib])], [eval ax_cv_cxx_compile_cxx11_lib_libcxx=yes], [eval ax_cv_cxx_compile_cxx11_lib_libcxx=no]) CXX="$ac_save_CXX"]) if eval test x$ax_cv_cxx_compile_cxx11_lib_libcxx = xyes; then CXX="$CXX -stdlib=libc++" ac_success=yes break fi fi if test x$ac_success = xno; then AC_MSG_ERROR([*** A C++ library with support for C++11 features is required.]) fi fi ]) capnproto-c++-1.1.0/src/0000755000175000017500000000000014731562205015536 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/CMakeLists.txt0000644000175000017500000000331614527152321020276 0ustar00kentonkenton00000000000000 # Tests ======================================================================== if(BUILD_TESTING) include(CTest) if(EXTERNAL_CAPNP) # Set up CAPNP_GENERATE_CPP for compiling test schemas find_package(CapnProto CONFIG QUIET) if(NOT CapnProto_FOUND) # No working installation of Cap'n Proto found, so fall back to searching the environment. # # We search for the external capnp compiler binaries via $CAPNP, $CAPNPC_CXX, and # find_program(). find_program() will use various paths in its search, among them # ${CMAKE_PREFIX_PATH}/bin and $PATH. if(NOT CAPNP_EXECUTABLE) if(DEFINED ENV{CAPNP}) set(CAPNP_EXECUTABLE "$ENV{CAPNP}") else() find_program(CAPNP_EXECUTABLE capnp) endif() endif() if(NOT CAPNPC_CXX_EXECUTABLE) if(DEFINED ENV{CAPNPC_CXX}) set(CAPNPC_CXX_EXECUTABLE "$ENV{CAPNPC_CXX}") else() # Also search in the same directory that `capnp` was found in get_filename_component(capnp_dir "${CAPNP_EXECUTABLE}" DIRECTORY) find_program(CAPNPC_CXX_EXECUTABLE capnpc-c++ HINTS "${capnp_dir}") endif() endif() endif() set(CAPNP_INCLUDE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") #TODO(someday) It would be nice to use targets instead of variables in CAPNP_GENERATE_CPP macro endif() # Sadly, we can't use the 'test' target, as that's coopted by ctest add_custom_target(check "${CMAKE_CTEST_COMMAND}" -V) endif() # BUILD_TESTING # kj =========================================================================== add_subdirectory(kj) # capnp ======================================================================== add_subdirectory(capnp) capnproto-c++-1.1.0/src/capnp/0000755000175000017500000000000014731562205016637 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/capnp/schema-loader-test.c++0000644000175000017500000003641014712011043022602 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #include "schema-loader.h" #include #include "test-util.h" #include namespace capnp { namespace _ { // private namespace { TEST(SchemaLoader, Load) { SchemaLoader loader; Schema struct32Schema = loader.load(Schema::from().getProto()); auto nativeSchema = Schema::from(); Schema testListsSchema = loader.load(nativeSchema.getProto()); Schema struct8Schema = loader.load(Schema::from().getProto()); Schema structPSchema = loader.load(Schema::from().getProto()); EXPECT_EQ(kj::str(nativeSchema.getProto()), kj::str(testListsSchema.getProto())); EXPECT_FALSE(testListsSchema == nativeSchema); EXPECT_FALSE(struct32Schema == Schema::from()); EXPECT_FALSE(struct8Schema == Schema::from()); EXPECT_FALSE(structPSchema == Schema::from()); EXPECT_TRUE(testListsSchema.getDependency(typeId()) == struct32Schema); EXPECT_TRUE(testListsSchema.getDependency(typeId()) == struct8Schema); EXPECT_TRUE(testListsSchema.getDependency(typeId()) == structPSchema); auto struct16Schema = testListsSchema.getDependency(typeId()); EXPECT_EQ(0u, struct16Schema.getProto().getStruct().getFields().size()); } TEST(SchemaLoader, LoadLateUnion) { SchemaLoader loader; StructSchema schema = loader.load(Schema::from().getProto()).asStruct(); loader.load(Schema::from().getProto()).asStruct(); loader.load(Schema::from().getProto()).asStruct(); EXPECT_EQ(6, schema.getDependency(schema.getFieldByName("theUnion").getProto().getGroup().getTypeId()) .asStruct().getFieldByName("grault").getProto().getOrdinal().getExplicit()); EXPECT_EQ(9, schema.getDependency(schema.getFieldByName("anotherUnion").getProto().getGroup().getTypeId()) .asStruct().getFieldByName("corge").getProto().getOrdinal().getExplicit()); EXPECT_TRUE(schema.findFieldByName("corge") == nullptr); EXPECT_TRUE(schema.findFieldByName("grault") == nullptr); } TEST(SchemaLoader, LoadUnnamedUnion) { SchemaLoader loader; StructSchema schema = loader.load(Schema::from().getProto()).asStruct(); EXPECT_TRUE(schema.findFieldByName("") == nullptr); EXPECT_TRUE(schema.findFieldByName("foo") != nullptr); EXPECT_TRUE(schema.findFieldByName("bar") != nullptr); EXPECT_TRUE(schema.findFieldByName("before") != nullptr); EXPECT_TRUE(schema.findFieldByName("after") != nullptr); } TEST(SchemaLoader, Use) { SchemaLoader loader; StructSchema schema = loader.load(Schema::from().getProto()).asStruct(); // Also have to load TestEnum. loader.load(Schema::from().getProto()); { MallocMessageBuilder builder; auto root = builder.getRoot(schema); initDynamicTestMessage(root); checkDynamicTestMessage(root.asReader()); // Can't convert to TestAllTypes because we didn't use loadCompiledTypeAndDependencies(). EXPECT_ANY_THROW(root.as()); // But if we reinterpret the raw bytes, it works. checkTestMessage(builder.getRoot()); } loader.loadCompiledTypeAndDependencies(); { MallocMessageBuilder builder; auto root = builder.getRoot(schema); initDynamicTestMessage(root); // Now we can actually cast. checkTestMessage(root.as()); } // Let's also test TestListDefaults, but as we do so, let's load the compiled types first, to // make sure the opposite order works. loader.loadCompiledTypeAndDependencies(); StructSchema testListsSchema = loader.get(typeId()).asStruct(); EXPECT_TRUE(testListsSchema != Schema::from()); { MallocMessageBuilder builder; auto root = builder.getRoot(testListsSchema); initDynamicTestLists(root); checkDynamicTestLists(root.asReader()); checkTestMessage(root.as()); } EXPECT_TRUE(loader.load(Schema::from().getProto()) == testListsSchema); { MallocMessageBuilder builder; auto root = builder.getRoot(testListsSchema); initDynamicTestLists(root); checkTestMessage(root.as()); } // Finally, let's test some unions. StructSchema unionSchema = loader.load(Schema::from().getProto()).asStruct(); loader.load(Schema::from().getProto()); loader.load(Schema::from().getProto()); { MallocMessageBuilder builder; auto root = builder.getRoot(unionSchema); root.get("union0").as().set("u0f1s16", 123); root.get("union1").as().set("u1f0sp", "hello"); auto reader = builder.getRoot().asReader(); EXPECT_EQ(123, reader.getUnion0().getU0f1s16()); EXPECT_EQ("hello", reader.getUnion1().getU1f0sp()); } } template Schema loadUnderAlternateTypeId(SchemaLoader& loader, uint64_t id) { MallocMessageBuilder schemaBuilder; schemaBuilder.setRoot(Schema::from().getProto()); auto root = schemaBuilder.getRoot(); root.setId(id); if (root.isStruct()) { // If the struct contains any self-referential members, change their type IDs as well. auto fields = root.getStruct().getFields(); for (auto field: fields) { if (field.isSlot()) { auto type = field.getSlot().getType(); if (type.isStruct() && type.getStruct().getTypeId() == typeId()) { type.getStruct().setTypeId(id); } } } } return loader.load(root); } TEST(SchemaLoader, Upgrade) { SchemaLoader loader; loader.loadCompiledTypeAndDependencies(); StructSchema schema = loader.get(typeId()).asStruct(); EXPECT_EQ(kj::str(Schema::from().getProto()), kj::str(schema.getProto())); loadUnderAlternateTypeId(loader, typeId()); // The new version replaced the old. EXPECT_EQ(Schema::from().getProto().getDisplayName(), schema.getProto().getDisplayName()); // But it is still usable as the old version. schema.requireUsableAs(); } TEST(SchemaLoader, Downgrade) { SchemaLoader loader; loader.loadCompiledTypeAndDependencies(); StructSchema schema = loader.get(typeId()).asStruct(); EXPECT_EQ(kj::str(Schema::from().getProto()), kj::str(schema.getProto())); loadUnderAlternateTypeId(loader, typeId()); // We kept the new version, because the replacement was older. EXPECT_EQ(Schema::from().getProto().getDisplayName(), schema.getProto().getDisplayName()); schema.requireUsableAs(); } TEST(SchemaLoader, Incompatible) { SchemaLoader loader; loader.loadCompiledTypeAndDependencies(); EXPECT_NONFATAL_FAILURE( loadUnderAlternateTypeId(loader, typeId())); } TEST(SchemaLoader, Enumerate) { SchemaLoader loader; loader.loadCompiledTypeAndDependencies(); auto list = loader.getAllLoaded(); ASSERT_EQ(2u, list.size()); if (list[0] == loader.get(typeId())) { EXPECT_TRUE(list[1] == loader.get(typeId())); } else { EXPECT_TRUE(list[0] == loader.get(typeId())); EXPECT_TRUE(list[1] == loader.get(typeId())); } } TEST(SchemaLoader, EnumerateNoPlaceholders) { SchemaLoader loader; Schema schema = loader.load(Schema::from().getProto()); { auto list = loader.getAllLoaded(); ASSERT_EQ(1u, list.size()); EXPECT_TRUE(list[0] == schema); } Schema dep = schema.getDependency(typeId()); { auto list = loader.getAllLoaded(); ASSERT_EQ(2u, list.size()); if (list[0] == schema) { EXPECT_TRUE(list[1] == dep); } else { EXPECT_TRUE(list[0] == dep); EXPECT_TRUE(list[1] == schema); } } } class FakeLoaderCallback: public SchemaLoader::LazyLoadCallback { public: FakeLoaderCallback(const schema::Node::Reader node): node(node), loaded(false) {} bool isLoaded() { return loaded; } void load(const SchemaLoader& loader, uint64_t id) const override { if (id == 1234) { // Magic "not found" ID. return; } EXPECT_EQ(node.getId(), id); EXPECT_FALSE(loaded); loaded = true; loader.loadOnce(node); } private: const schema::Node::Reader node; mutable bool loaded = false; }; TEST(SchemaLoader, LazyLoad) { FakeLoaderCallback callback(Schema::from().getProto()); SchemaLoader loader(callback); EXPECT_TRUE(loader.tryGet(1234) == nullptr); EXPECT_FALSE(callback.isLoaded()); Schema schema = loader.get(typeId()); EXPECT_TRUE(callback.isLoaded()); EXPECT_EQ(schema.getProto().getDisplayName(), Schema::from().getProto().getDisplayName()); EXPECT_EQ(schema, schema.getDependency(typeId())); EXPECT_EQ(schema, loader.get(typeId())); } TEST(SchemaLoader, LazyLoadGetDependency) { FakeLoaderCallback callback(Schema::from().getProto()); SchemaLoader loader(callback); Schema schema = loader.load(Schema::from().getProto()); EXPECT_FALSE(callback.isLoaded()); Schema dep = schema.getDependency(typeId()); EXPECT_TRUE(callback.isLoaded()); EXPECT_EQ(dep.getProto().getDisplayName(), Schema::from().getProto().getDisplayName()); EXPECT_EQ(dep, schema.getDependency(typeId())); EXPECT_EQ(dep, loader.get(typeId())); } TEST(SchemaLoader, Generics) { SchemaLoader loader; StructSchema allTypes = loader.load(Schema::from().getProto()).asStruct(); StructSchema tap = loader.load(Schema::from().getProto()).asStruct(); loader.load(Schema::from::Inner>().getProto()); loader.load(Schema::from::Inner2<>>().getProto()); loader.load(Schema::from::Interface<>>().getProto()); loader.load(Schema::from::Interface<>::CallResults>().getProto()); loader.load(Schema::from>().getProto()); StructSchema schema = loader.load(Schema::from().getProto()).asStruct(); StructSchema branded; { StructSchema::Field basic = schema.getFieldByName("basic"); branded = basic.getType().asStruct(); StructSchema::Field foo = branded.getFieldByName("foo"); EXPECT_TRUE(foo.getType().asStruct() == allTypes); EXPECT_TRUE(foo.getType().asStruct() != tap); StructSchema instance2 = branded.getFieldByName("rev").getType().asStruct(); StructSchema::Field foo2 = instance2.getFieldByName("foo"); EXPECT_TRUE(foo2.getType().asStruct() == tap); EXPECT_TRUE(foo2.getType().asStruct() != allTypes); } { StructSchema inner2 = schema.getFieldByName("inner2").getType().asStruct(); StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct(); Type boundFoo = bound.getFieldByName("foo").getType(); EXPECT_FALSE(boundFoo.isAnyPointer()); EXPECT_TRUE(boundFoo.asStruct() == allTypes); StructSchema unbound = inner2.getFieldByName("innerUnbound").getType().asStruct(); Type unboundFoo = unbound.getFieldByName("foo").getType(); EXPECT_TRUE(unboundFoo.isAnyPointer()); } { InterfaceSchema cap = schema.getFieldByName("genericCap").getType().asInterface(); InterfaceSchema::Method method = cap.getMethodByName("call"); StructSchema inner2 = method.getParamType(); StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct(); Type boundFoo = bound.getFieldByName("foo").getType(); EXPECT_FALSE(boundFoo.isAnyPointer()); EXPECT_TRUE(boundFoo.asStruct() == allTypes); EXPECT_TRUE(inner2.getFieldByName("baz").getType().isText()); StructSchema results = method.getResultType(); EXPECT_TRUE(results.getFieldByName("qux").getType().isData()); EXPECT_TRUE(results.getFieldByName("gen").getType().asStruct() == branded); } } TEST(SchemaLoader, LoadStreaming) { SchemaLoader loader; InterfaceSchema schema = loader.load(Schema::from().getProto()).asInterface(); auto results = schema.getMethodByName("doStreamI").getResultType(); KJ_EXPECT(results.isStreamResult()); KJ_EXPECT(results.getShortDisplayName() == "StreamResult", results.getShortDisplayName()); } KJ_TEST("SchemaLoader placeholders are assumed to have caps") { // Load TestCycle*NoCaps, but don't load its dependency TestAllTypes, so the loader has to assume // there may be caps. { SchemaLoader loader; Schema schemaA = loader.load(Schema::from().getProto()); Schema schemaB = loader.load(Schema::from().getProto()); loader.computeOptimizationHints(); KJ_EXPECT(schemaA.asStruct().mayContainCapabilities()); KJ_EXPECT(schemaB.asStruct().mayContainCapabilities()); } // Try again, but actually load TestAllTypes. Now we recognize there's no caps. { SchemaLoader loader; Schema schemaA = loader.load(Schema::from().getProto()); Schema schemaB = loader.load(Schema::from().getProto()); loader.load(Schema::from().getProto()); loader.computeOptimizationHints(); KJ_EXPECT(!schemaA.asStruct().mayContainCapabilities()); KJ_EXPECT(!schemaB.asStruct().mayContainCapabilities()); } // NOTE: computeOptimizationHints() is also tested in `schema-test.c++` where we test that // various compiled types have the correct hints, which relies on the code generator having // computed the hints. } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/membrane-test.c++0000644000175000017500000003460214712011043021665 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "membrane.h" #include #include "test-util.h" #include #include #include "rpc-twoparty.h" namespace capnp { namespace _ { namespace { using Thing = test::TestMembrane::Thing; class ThingImpl final: public Thing::Server { public: ThingImpl(kj::StringPtr text): text(text) {} protected: kj::Promise passThrough(PassThroughContext context) override { context.getResults().setText(text); return kj::READY_NOW; } kj::Promise intercept(InterceptContext context) override { context.getResults().setText(text); return kj::READY_NOW; } private: kj::StringPtr text; }; class TestMembraneImpl final: public test::TestMembrane::Server { protected: kj::Promise makeThing(MakeThingContext context) override { context.getResults().setThing(kj::heap("inside")); return kj::READY_NOW; } kj::Promise callPassThrough(CallPassThroughContext context) override { auto params = context.getParams(); auto req = params.getThing().passThroughRequest(); if (params.getTailCall()) { return context.tailCall(kj::mv(req)); } else { return req.send().then( [KJ_CPCAP(context)](Response&& result) mutable { context.setResults(result); }); } } kj::Promise callIntercept(CallInterceptContext context) override { auto params = context.getParams(); auto req = params.getThing().interceptRequest(); if (params.getTailCall()) { return context.tailCall(kj::mv(req)); } else { return req.send().then( [KJ_CPCAP(context)](Response&& result) mutable { context.setResults(result); }); } } kj::Promise loopback(LoopbackContext context) override { context.getResults().setThing(context.getParams().getThing()); return kj::READY_NOW; } kj::Promise waitForever(WaitForeverContext context) override { return kj::NEVER_DONE; } }; class MembranePolicyImpl: public MembranePolicy, public kj::Refcounted { public: MembranePolicyImpl() = default; MembranePolicyImpl(kj::Maybe> revokePromise) : revokePromise(revokePromise.map([](kj::Promise& p) { return p.fork(); })) {} kj::Maybe inboundCall(uint64_t interfaceId, uint16_t methodId, Capability::Client target) override { if (interfaceId == capnp::typeId() && methodId == 1) { return Capability::Client(kj::heap("inbound")); } else { return nullptr; } } kj::Maybe outboundCall(uint64_t interfaceId, uint16_t methodId, Capability::Client target) override { if (interfaceId == capnp::typeId() && methodId == 1) { return Capability::Client(kj::heap("outbound")); } else { return nullptr; } } kj::Own addRef() override { return kj::addRef(*this); } kj::Maybe> onRevoked() override { return revokePromise.map([](kj::ForkedPromise& fork) { return fork.addBranch(); }); } bool shouldResolveBeforeRedirecting() override { return true; } private: kj::Maybe> revokePromise; }; void testThingImpl(kj::WaitScope& waitScope, test::TestMembrane::Client membraned, kj::Function makeThing, kj::StringPtr localPassThrough, kj::StringPtr localIntercept, kj::StringPtr remotePassThrough, kj::StringPtr remoteIntercept) { KJ_EXPECT(makeThing().passThroughRequest().send().wait(waitScope).getText() == localPassThrough); KJ_EXPECT(makeThing().interceptRequest().send().wait(waitScope).getText() == localIntercept); { auto req = membraned.callPassThroughRequest(); req.setThing(makeThing()); req.setTailCall(false); KJ_EXPECT(req.send().wait(waitScope).getText() == remotePassThrough); } { auto req = membraned.callInterceptRequest(); req.setThing(makeThing()); req.setTailCall(false); KJ_EXPECT(req.send().wait(waitScope).getText() == remoteIntercept); } { auto req = membraned.callPassThroughRequest(); req.setThing(makeThing()); req.setTailCall(true); KJ_EXPECT(req.send().wait(waitScope).getText() == remotePassThrough); } { auto req = membraned.callInterceptRequest(); req.setThing(makeThing()); req.setTailCall(true); KJ_EXPECT(req.send().wait(waitScope).getText() == remoteIntercept); } } struct TestEnv { kj::EventLoop loop; kj::WaitScope waitScope; kj::Own policy; test::TestMembrane::Client membraned; TestEnv() : waitScope(loop), policy(kj::refcounted()), membraned(membrane(kj::heap(), policy->addRef())) {} void testThing(kj::Function makeThing, kj::StringPtr localPassThrough, kj::StringPtr localIntercept, kj::StringPtr remotePassThrough, kj::StringPtr remoteIntercept) { testThingImpl(waitScope, membraned, kj::mv(makeThing), localPassThrough, localIntercept, remotePassThrough, remoteIntercept); } }; KJ_TEST("call local object inside membrane") { TestEnv env; env.testThing([&]() { return env.membraned.makeThingRequest().send().wait(env.waitScope).getThing(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call local promise inside membrane") { TestEnv env; env.testThing([&]() { return env.membraned.makeThingRequest().send().getThing(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call local resolved promise inside membrane") { TestEnv env; env.testThing([&]() { auto thing = env.membraned.makeThingRequest().send().getThing(); thing.whenResolved().wait(env.waitScope); return thing; }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call local object outside membrane") { TestEnv env; env.testThing([&]() { return kj::heap("outside"); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("call local capability that has passed into and back out of membrane") { TestEnv env; env.testThing([&]() { auto req = env.membraned.loopbackRequest(); req.setThing(kj::heap("outside")); return req.send().wait(env.waitScope).getThing(); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("call local promise pointing into membrane that eventually resolves to outside") { TestEnv env; env.testThing([&]() { auto req = env.membraned.loopbackRequest(); req.setThing(kj::heap("outside")); return req.send().getThing(); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("apply membrane using copyOutOfMembrane() on struct") { TestEnv env; env.testThing([&]() { MallocMessageBuilder outsideBuilder; auto root = outsideBuilder.initRoot(); root.setCap(kj::heap("inside")); MallocMessageBuilder insideBuilder; insideBuilder.adoptRoot(copyOutOfMembrane( root.asReader(), insideBuilder.getOrphanage(), env.policy->addRef())); return insideBuilder.getRoot().getCap(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("apply membrane using copyOutOfMembrane() on list") { TestEnv env; env.testThing([&]() { MallocMessageBuilder outsideBuilder; auto list = outsideBuilder.initRoot().initList(1); list.set(0, kj::heap("inside")); MallocMessageBuilder insideBuilder; insideBuilder.initRoot().adoptList(copyOutOfMembrane( list.asReader(), insideBuilder.getOrphanage(), env.policy->addRef())); return insideBuilder.getRoot().getList()[0]; }, "inside", "inbound", "inside", "inside"); } KJ_TEST("apply membrane using copyOutOfMembrane() on AnyPointer") { TestEnv env; env.testThing([&]() { MallocMessageBuilder outsideBuilder; auto ptr = outsideBuilder.initRoot().getAnyPointerField(); ptr.setAs(kj::heap("inside")); MallocMessageBuilder insideBuilder; insideBuilder.initRoot().getAnyPointerField().adopt(copyOutOfMembrane( ptr.asReader(), insideBuilder.getOrphanage(), env.policy->addRef())); return insideBuilder.getRoot().getAnyPointerField() .getAs(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("MembraneHook::whenMoreResolved returns same value even when called concurrently.") { TestEnv env; auto paf = kj::newPromiseAndFulfiller(); test::TestMembrane::Client promCap(kj::mv(paf.promise)); auto prom = promCap.whenResolved(); prom = prom.then([promCap = kj::mv(promCap), &env]() mutable { auto membraned = membrane(kj::mv(promCap), env.policy->addRef()); auto hook = ClientHook::from(membraned); auto arr = kj::heapArrayBuilder>>(2); arr.add(KJ_ASSERT_NONNULL(hook->whenMoreResolved())); arr.add(KJ_ASSERT_NONNULL(hook->whenMoreResolved())); return kj::joinPromises(arr.finish()).attach(kj::mv(hook)); }).then([](kj::Vector> hooks) { auto first = hooks[0].get(); auto second = hooks[1].get(); KJ_ASSERT(first == second); }).eagerlyEvaluate(nullptr); auto newClient = kj::heap(); paf.fulfiller->fulfill(kj::mv(newClient)); prom.wait(env.waitScope); } struct TestRpcEnv { kj::EventLoop loop; kj::WaitScope waitScope; kj::TwoWayPipe pipe; TwoPartyClient client; TwoPartyClient server; test::TestMembrane::Client membraned; TestRpcEnv(kj::Maybe> revokePromise = nullptr) : waitScope(loop), pipe(kj::newTwoWayPipe()), client(*pipe.ends[0]), server(*pipe.ends[1], membrane(kj::heap(), kj::refcounted(kj::mv(revokePromise))), rpc::twoparty::Side::SERVER), membraned(client.bootstrap().castAs()) {} void testThing(kj::Function makeThing, kj::StringPtr localPassThrough, kj::StringPtr localIntercept, kj::StringPtr remotePassThrough, kj::StringPtr remoteIntercept) { testThingImpl(waitScope, membraned, kj::mv(makeThing), localPassThrough, localIntercept, remotePassThrough, remoteIntercept); } }; KJ_TEST("call remote object inside membrane") { TestRpcEnv env; env.testThing([&]() { return env.membraned.makeThingRequest().send().wait(env.waitScope).getThing(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call remote promise inside membrane") { TestRpcEnv env; env.testThing([&]() { return env.membraned.makeThingRequest().send().getThing(); }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call remote resolved promise inside membrane") { TestEnv env; env.testThing([&]() { auto thing = env.membraned.makeThingRequest().send().getThing(); thing.whenResolved().wait(env.waitScope); return thing; }, "inside", "inbound", "inside", "inside"); } KJ_TEST("call remote object outside membrane") { TestRpcEnv env; env.testThing([&]() { return kj::heap("outside"); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("call remote capability that has passed into and back out of membrane") { TestRpcEnv env; env.testThing([&]() { auto req = env.membraned.loopbackRequest(); req.setThing(kj::heap("outside")); return req.send().wait(env.waitScope).getThing(); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("call remote promise pointing into membrane that eventually resolves to outside") { TestRpcEnv env; env.testThing([&]() { auto req = env.membraned.loopbackRequest(); req.setThing(kj::heap("outside")); return req.send().getThing(); }, "outside", "outside", "outside", "outbound"); } KJ_TEST("revoke membrane") { auto paf = kj::newPromiseAndFulfiller(); TestRpcEnv env(kj::mv(paf.promise)); auto thing = env.membraned.makeThingRequest().send().wait(env.waitScope).getThing(); auto callPromise = env.membraned.waitForeverRequest().send(); KJ_EXPECT(!callPromise.poll(env.waitScope)); paf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "foobar")); // TRICKY: We need to use .ignoreResult().wait() below because when compiling with // -fno-exceptions, void waits throw recoverable exceptions while non-void waits necessarily // throw fatal exceptions... but testing for fatal exceptions when exceptions are disabled // involves fork()ing the process to run the code so if it has side effects on file descriptors // then we'll get in a bad state... KJ_ASSERT(callPromise.poll(env.waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", callPromise.ignoreResult().wait(env.waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", env.membraned.makeThingRequest().send().ignoreResult().wait(env.waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", thing.passThroughRequest().send().ignoreResult().wait(env.waitScope)); } } // namespace } // namespace _ } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc.c++0000644000175000017500000045143114731420004017713 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "rpc.h" #include "message.h" #include #include #include #include #include #include // std::greater #include #include #include #include #include #include namespace capnp { namespace _ { // private namespace { template inline constexpr uint messageSizeHint() { return 1 + sizeInWords() + sizeInWords(); } template <> inline constexpr uint messageSizeHint() { return 1 + sizeInWords(); } constexpr const uint MESSAGE_TARGET_SIZE_HINT = sizeInWords() + sizeInWords() + 16; // +16 for ops; hope that's enough constexpr const uint CAP_DESCRIPTOR_SIZE_HINT = sizeInWords() + sizeInWords(); constexpr const uint64_t MAX_SIZE_HINT = 1 << 20; uint copySizeHint(MessageSize size) { uint64_t sizeHint = size.wordCount + size.capCount * CAP_DESCRIPTOR_SIZE_HINT // if capCount > 0, the cap descriptor list has a 1-word tag + (size.capCount > 0); return kj::min(MAX_SIZE_HINT, sizeHint); } uint firstSegmentSize(kj::Maybe sizeHint, uint additional) { KJ_IF_MAYBE(s, sizeHint) { return copySizeHint(*s) + additional; } else { return 0; } } kj::Maybe> toPipelineOps(List::Reader ops) { auto result = kj::heapArrayBuilder(ops.size()); for (auto opReader: ops) { PipelineOp op; switch (opReader.which()) { case rpc::PromisedAnswer::Op::NOOP: op.type = PipelineOp::NOOP; break; case rpc::PromisedAnswer::Op::GET_POINTER_FIELD: op.type = PipelineOp::GET_POINTER_FIELD; op.pointerIndex = opReader.getGetPointerField(); break; default: KJ_FAIL_REQUIRE("Unsupported pipeline op.", (uint)opReader.which()) { return nullptr; } } result.add(op); } return result.finish(); } Orphan> fromPipelineOps( Orphanage orphanage, kj::ArrayPtr ops) { auto result = orphanage.newOrphan>(ops.size()); auto builder = result.get(); for (uint i: kj::indices(ops)) { rpc::PromisedAnswer::Op::Builder opBuilder = builder[i]; switch (ops[i].type) { case PipelineOp::NOOP: opBuilder.setNoop(); break; case PipelineOp::GET_POINTER_FIELD: opBuilder.setGetPointerField(ops[i].pointerIndex); break; } } return result; } kj::Exception toException(const rpc::Exception::Reader& exception) { auto reason = [&]() { if (exception.getReason().startsWith("remote exception: ")) { return kj::str(exception.getReason()); } else { return kj::str("remote exception: ", exception.getReason()); } }(); kj::Exception result(static_cast(exception.getType()), "(remote)", 0, kj::mv(reason)); if (exception.hasTrace()) { result.setRemoteTrace(kj::str(exception.getTrace())); } return result; } void fromException(const kj::Exception& exception, rpc::Exception::Builder builder, kj::Maybe&> traceEncoder) { kj::StringPtr description = exception.getDescription(); // Include context, if any. kj::Vector contextLines; for (auto context = exception.getContext();;) { KJ_IF_MAYBE(c, context) { contextLines.add(kj::str("context: ", c->file, ": ", c->line, ": ", c->description)); context = c->next; } else { break; } } kj::String scratch; if (contextLines.size() > 0) { scratch = kj::str(description, '\n', kj::strArray(contextLines, "\n")); description = scratch; } builder.setReason(description); builder.setType(static_cast(exception.getType())); KJ_IF_MAYBE(t, traceEncoder) { builder.setTrace((*t)(exception)); } if (exception.getType() == kj::Exception::Type::FAILED && !exception.getDescription().startsWith("remote exception:")) { KJ_LOG(INFO, "returning failure over rpc", exception); } } uint exceptionSizeHint(const kj::Exception& exception) { return sizeInWords() + exception.getDescription().size() / sizeof(word) + 1; } ClientHook::CallHints callHintsFromReader(rpc::Call::Reader reader) { ClientHook::CallHints hints; hints.noPromisePipelining = reader.getNoPromisePipelining(); hints.onlyPromisePipeline = reader.getOnlyPromisePipeline(); return hints; } // ======================================================================================= template static constexpr Id highBit() { return 1u << (sizeof(Id) * 8 - 1); } template class ExportTable { // Table mapping integers to T, where the integers are chosen locally. public: bool isHigh(Id& id) { return (id & highBit()) != 0; } kj::Maybe find(Id id) { if (isHigh(id)) { return highSlots.find(id); } else if (id < slots.size() && slots[id] != nullptr) { return slots[id]; } else { return nullptr; } } T erase(Id id, T& entry) { // Remove an entry from the table and return it. We return it so that the caller can be // careful to release it (possibly invoking arbitrary destructors) at a time that makes sense. // `entry` is a reference to the entry being released -- we require this in order to prove // that the caller has already done a find() to check that this entry exists. We can't check // ourselves because the caller may have nullified the entry in the meantime. if (isHigh(id)) { auto& slot = KJ_REQUIRE_NONNULL(highSlots.findEntry(id)); return highSlots.release(slot).value; } else { KJ_DREQUIRE(&entry == &slots[id]); T toRelease = kj::mv(slots[id]); slots[id] = T(); freeIds.push(id); return toRelease; } } T& next(Id& id) { if (freeIds.empty()) { id = slots.size(); KJ_ASSERT(!isHigh(id), "2^31 concurrent questions?!!?!"); return slots.add(); } else { id = freeIds.top(); freeIds.pop(); return slots[id]; } } T& nextHigh(Id& id) { // Choose an ID with the top bit set in round-robin fashion, but don't choose an ID that // is still in use. KJ_ASSERT(highSlots.size() < Id(kj::maxValue) / 2); // avoid infinite loop below. bool created = false; T* slot; while (!created) { id = highCounter++ | highBit(); slot = &highSlots.findOrCreate(id, [&]() { created = true; return typename kj::HashMap::Entry { id, T() }; }); } return *slot; } template void forEach(Func&& func) { for (Id i = 0; i < slots.size(); i++) { if (slots[i] != nullptr) { func(i, slots[i]); } } for (auto& slot: highSlots) { func(slot.key, slot.value); } } void release() { // Release memory backing the table. { auto drop = kj::mv(slots); } { auto drop = kj::mv(freeIds); } { auto drop = kj::mv(highSlots); } } private: kj::Vector slots; std::priority_queue, std::greater> freeIds; kj::HashMap highSlots; Id highCounter = 0; }; template class ImportTable { // Table mapping integers to T, where the integers are chosen remotely. public: T& operator[](Id id) { if (id < kj::size(low)) { return low[id]; } else { return high[id]; } } kj::Maybe find(Id id) { if (id < kj::size(low)) { return low[id]; } else { auto iter = high.find(id); if (iter == high.end()) { return nullptr; } else { return iter->second; } } } T erase(Id id) { // Remove an entry from the table and return it. We return it so that the caller can be // careful to release it (possibly invoking arbitrary destructors) at a time that makes sense. if (id < kj::size(low)) { T toRelease = kj::mv(low[id]); low[id] = T(); return toRelease; } else { T toRelease = kj::mv(high[id]); high.erase(id); return toRelease; } } template void forEach(Func&& func) { for (Id i: kj::indices(low)) { func(i, low[i]); } for (auto& entry: high) { func(entry.first, entry.second); } } private: T low[16]; std::unordered_map high; }; // ======================================================================================= class RpcConnectionState final: public kj::TaskSet::ErrorHandler, public kj::Refcounted { public: struct DisconnectInfo { kj::Promise shutdownPromise; // Task which is working on sending an abort message and cleanly ending the connection. }; RpcConnectionState(BootstrapFactoryBase& bootstrapFactory, kj::Maybe restorer, kj::Own&& connectionParam, kj::Own>&& disconnectFulfiller, size_t flowLimit, kj::Maybe&> traceEncoder) : bootstrapFactory(bootstrapFactory), restorer(restorer), disconnectFulfiller(kj::mv(disconnectFulfiller)), flowLimit(flowLimit), traceEncoder(traceEncoder), tasks(*this) { connection.init(kj::mv(connectionParam)); tasks.add(messageLoop()); } kj::Own restore(AnyPointer::Reader objectId) { if (connection.is()) { return newBrokenCap(kj::cp(connection.get())); } QuestionId questionId; auto& question = questions.next(questionId); question.isAwaitingReturn = true; auto paf = kj::newPromiseAndFulfiller>>(); auto questionRef = kj::refcounted(*this, questionId, kj::mv(paf.fulfiller)); question.selfRef = *questionRef; paf.promise = paf.promise.attach(kj::addRef(*questionRef)); { auto message = connection.get()->newOutgoingMessage( objectId.targetSize().wordCount + messageSizeHint()); auto builder = message->getBody().initAs().initBootstrap(); builder.setQuestionId(questionId); builder.getDeprecatedObjectId().set(objectId); message->send(); } auto pipeline = kj::refcounted(*this, kj::mv(questionRef), kj::mv(paf.promise)); return pipeline->getPipelinedCap(kj::Array(nullptr)); } void taskFailed(kj::Exception&& exception) override { disconnect(kj::mv(exception)); } void disconnect(kj::Exception&& exception) { // Shut down the connection with the given error. // // This will cancel `tasks`, so cannot be called from inside a task in `tasks`. Instead, use // `tasks.add(exception)` to schedule a shutdown, since any error thrown by a task will be // passed to `disconnect()` later. // After disconnect(), the RpcSystem could be destroyed, making `traceEncoder` a dangling // reference, so null it out before we return from here. We don't need it anymore once // disconnected anyway. KJ_DEFER(traceEncoder = nullptr); if (!connection.is()) { // Already disconnected. return; } kj::Exception networkException(kj::Exception::Type::DISCONNECTED, exception.getFile(), exception.getLine(), kj::heapString(exception.getDescription())); // Don't throw away the stack trace. if (exception.getRemoteTrace() != nullptr) { networkException.setRemoteTrace(kj::str(exception.getRemoteTrace())); } for (void* addr: exception.getStackTrace()) { networkException.addTrace(addr); } // If your stack trace points here, it means that the exception became the reason that the // RPC connection was disconnected. The exception was then thrown by all in-flight calls and // all future calls on this connection. networkException.addTraceHere(); // Set our connection state to Disconnected now so that no one tries to write any messages to // it in their destructors. auto dyingConnection = kj::mv(connection.get()); connection.init(kj::cp(networkException)); KJ_IF_MAYBE(newException, kj::runCatchingExceptions([&]() { // Carefully pull all the objects out of the tables prior to releasing them because their // destructors could come back and mess with the tables. kj::Vector> pipelinesToRelease; kj::Vector> clientsToRelease; kj::Vector tasksToRelease; kj::Vector> resolveOpsToRelease; KJ_DEFER(tasks.clear()); // All current questions complete with exceptions. questions.forEach([&](QuestionId id, Question& question) { KJ_IF_MAYBE(questionRef, question.selfRef) { // QuestionRef still present. questionRef->reject(kj::cp(networkException)); // We need to fully disconnect each QuestionRef otherwise it holds a reference back to // the connection state. Meanwhile `tasks` may hold streaming calls that end up holding // these QuestionRefs. Technically this is a cyclic reference, but as long as the cycle // is broken on disconnect (which happens when the RpcSystem itself is destroyed), then // we're OK. questionRef->disconnect(); } }); // Since we've disconnected the QuestionRefs, they won't clean up the questions table for // us, so do that here. questions.release(); answers.forEach([&](AnswerId id, Answer& answer) { KJ_IF_MAYBE(p, answer.pipeline) { pipelinesToRelease.add(kj::mv(*p)); } tasksToRelease.add(kj::mv(answer.task)); KJ_IF_MAYBE(context, answer.callContext) { context->finish(); } }); exports.forEach([&](ExportId id, Export& exp) { clientsToRelease.add(kj::mv(exp.clientHook)); KJ_IF_MAYBE(op, exp.resolveOp) { resolveOpsToRelease.add(kj::mv(*op)); } exp = Export(); }); imports.forEach([&](ImportId id, Import& import) { KJ_IF_MAYBE(f, import.promiseFulfiller) { f->get()->reject(kj::cp(networkException)); } }); embargoes.forEach([&](EmbargoId id, Embargo& embargo) { KJ_IF_MAYBE(f, embargo.fulfiller) { f->get()->reject(kj::cp(networkException)); } }); })) { // Some destructor must have thrown an exception. There is no appropriate place to report // these errors. KJ_LOG(ERROR, "Uncaught exception when destroying capabilities dropped by disconnect.", *newException); } // Send an abort message, but ignore failure. kj::runCatchingExceptions([&]() { auto message = dyingConnection->newOutgoingMessage( messageSizeHint() + exceptionSizeHint(exception)); fromException(exception, message->getBody().getAs().initAbort()); message->send(); }); // Indicate disconnect. auto shutdownPromise = dyingConnection->shutdown() .attach(kj::mv(dyingConnection)) .then([]() -> kj::Promise { return kj::READY_NOW; }, [self = kj::addRef(*this), origException = kj::mv(exception)]( kj::Exception&& shutdownException) -> kj::Promise { // Don't report disconnects as an error. if (shutdownException.getType() == kj::Exception::Type::DISCONNECTED) { return kj::READY_NOW; } // If the error is just what was passed in to disconnect(), don't report it back out // since it shouldn't be anything the caller doesn't already know about. if (shutdownException.getType() == origException.getType() && shutdownException.getDescription() == origException.getDescription()) { return kj::READY_NOW; } // We are shutting down after receive error, ignore shutdown exception since underlying // transport is probably broken. if (self->receiveIncomingMessageError) { return kj::READY_NOW; } return kj::mv(shutdownException); }); disconnectFulfiller->fulfill(DisconnectInfo { kj::mv(shutdownPromise) }); canceler.cancel(networkException); } void setFlowLimit(size_t words) { flowLimit = words; maybeUnblockFlow(); } private: class RpcClient; class ImportClient; class PromiseClient; class QuestionRef; class RpcPipeline; class RpcCallContext; class RpcResponse; // ======================================================================================= // The Four Tables entry types // // We have to define these before we can define the class's fields. typedef uint32_t QuestionId; typedef QuestionId AnswerId; typedef uint32_t ExportId; typedef ExportId ImportId; // See equivalent definitions in rpc.capnp. // // We always use the type that refers to the local table of the same name. So e.g. although // QuestionId and AnswerId are the same type, we use QuestionId when referring to an entry in // the local question table (which corresponds to the peer's answer table) and use AnswerId // to refer to an entry in our answer table (which corresponds to the peer's question table). // Since all messages in the RPC protocol are defined from the sender's point of view, this // means that any time we read an ID from a received message, its type should invert. // TODO(cleanup): Perhaps we could enforce that in a type-safe way? Hmm... struct Question { kj::Array paramExports; // List of exports that were sent in the request. If the response has `releaseParamCaps` these // will need to be released. kj::Maybe selfRef; // The local QuestionRef, set to nullptr when it is destroyed, which is also when `Finish` is // sent. bool isAwaitingReturn = false; // True from when `Call` is sent until `Return` is received. bool isTailCall = false; // Is this a tail call? If so, we don't expect to receive results in the `Return`. bool skipFinish = false; // If true, don't send a Finish message. // // This is used in two cases: // * The `Return` message had the `noFinishNeeded` hint. // * Our attempt to send the `Call` threw an exception, therefore the peer never even received // the call in the first place and would not expect a `Finish`. inline bool operator==(decltype(nullptr)) const { return !isAwaitingReturn && selfRef == nullptr; } inline bool operator!=(decltype(nullptr)) const { return !operator==(nullptr); } }; struct Answer { Answer() = default; Answer(const Answer&) = delete; Answer(Answer&&) = default; Answer& operator=(Answer&&) = default; // If we don't explicitly write all this, we get some stupid error deep in STL. bool active = false; // True from the point when the Call message is received to the point when both the `Finish` // message has been received and the `Return` has been sent. kj::Maybe> pipeline; // Send pipelined calls here. Becomes null as soon as a `Finish` is received. using Running = kj::Promise; struct Finished {}; using Redirected = kj::Promise>; kj::OneOf task; // While the RPC is running locally, `task` is a `Promise` representing the task to execute // the RPC. // // When `Finish` is received (and results are not redirected), `task` becomes `Finished`, which // cancels it if it's still running. // // For locally-redirected calls (Call.sendResultsTo.yourself), this is a promise for the call // result, to be picked up by a subsequent `Return`. kj::Maybe callContext; // The call context, if it's still active. Becomes null when the `Return` message is sent. // This object, if non-null, is owned by `asyncOp`. kj::Array resultExports; // List of exports that were sent in the results. If the finish has `releaseResultCaps` these // will need to be released. }; struct Export { uint refcount = 0; // When this reaches 0, drop `clientHook` and free this export. kj::Own clientHook; kj::Maybe> resolveOp = nullptr; // If this export is a promise (not a settled capability), the `resolveOp` represents the // ongoing operation to wait for that promise to resolve and then send a `Resolve` message. inline bool operator==(decltype(nullptr)) const { return refcount == 0; } inline bool operator!=(decltype(nullptr)) const { return refcount != 0; } }; struct Import { Import() = default; Import(const Import&) = delete; Import(Import&&) = default; Import& operator=(Import&&) = default; // If we don't explicitly write all this, we get some stupid error deep in STL. kj::Maybe importClient; // Becomes null when the import is destroyed. kj::Maybe appClient; // Either a copy of importClient, or, in the case of promises, the wrapping PromiseClient. // Becomes null when it is discarded *or* when the import is destroyed (e.g. the promise is // resolved and the import is no longer needed). kj::Maybe>>> promiseFulfiller; // If non-null, the import is a promise. }; typedef uint32_t EmbargoId; struct Embargo { // For handling the `Disembargo` message when looping back to self. kj::Maybe>> fulfiller; // Fulfill this when the Disembargo arrives. inline bool operator==(decltype(nullptr)) const { return fulfiller == nullptr; } inline bool operator!=(decltype(nullptr)) const { return fulfiller != nullptr; } }; // ======================================================================================= // OK, now we can define RpcConnectionState's member data. BootstrapFactoryBase& bootstrapFactory; kj::Maybe restorer; typedef kj::Own Connected; typedef kj::Exception Disconnected; kj::OneOf connection; // Once the connection has failed, we drop it and replace it with an exception, which will be // thrown from all further calls. kj::Canceler canceler; // Will be canceled if and when `connection` is changed from `Connected` to `Disconnected`. // TODO(cleanup): `Connected` should be a struct that contains the connection and the Canceler, // but that's more refactoring than I want to do right now. kj::Own> disconnectFulfiller; ExportTable exports; ExportTable questions; ImportTable answers; ImportTable imports; // The Four Tables! // The order of the tables is important for correct destruction. std::unordered_map exportsByCap; // Maps already-exported ClientHook objects to their ID in the export table. ExportTable embargoes; // There are only four tables. This definitely isn't a fifth table. I don't know what you're // talking about. size_t flowLimit; size_t callWordsInFlight = 0; kj::Maybe>> flowWaiter; // If non-null, we're currently blocking incoming messages waiting for callWordsInFlight to drop // below flowLimit. Fulfill this to un-block. kj::Maybe&> traceEncoder; kj::TaskSet tasks; bool gotReturnForHighQuestionId = false; // Becomes true if we ever get a `Return` message for a high question ID (with top bit set), // which we use in cases where we've hinted to the peer that we don't want a `Return`. If the // peer sends us one anyway then it seemingly doesn't not implement our hints. We need to stop // using the hints in this case before the high question ID space wraps around since otherwise // we might reuse an ID that the peer thinks is still in use. bool sentCapabilitiesInPipelineOnlyCall = false; // Becomes true if `sendPipelineOnly()` is ever called with parameters that include capabilities. bool receiveIncomingMessageError = false; // Becomes true when receiveIncomingMessage resulted in exception. // ===================================================================================== // ClientHook implementations class RpcClient: public ClientHook, public kj::Refcounted { public: RpcClient(RpcConnectionState& connectionState) : connectionState(kj::addRef(connectionState)) {} ~RpcClient() noexcept(false) { KJ_IF_MAYBE(f, this->flowController) { // Destroying the client should not cancel outstanding streaming calls. connectionState->tasks.add(f->get()->waitAllAcked().attach(kj::mv(*f))); } } virtual kj::Maybe writeDescriptor(rpc::CapDescriptor::Builder descriptor, kj::Vector& fds) = 0; // Writes a CapDescriptor referencing this client. The CapDescriptor must be sent as part of // the very next message sent on the connection, as it may become invalid if other things // happen. // // If writing the descriptor adds a new export to the export table, or increments the refcount // on an existing one, then the ID is returned and the caller is responsible for removing it // later. virtual kj::Maybe> writeTarget( rpc::MessageTarget::Builder target) = 0; // Writes the appropriate call target for calls to this capability and returns null. // // - OR - // // If calls have been redirected to some other local ClientHook, returns that hook instead. // This can happen if the capability represents a promise that has been resolved. virtual kj::Own getInnermostClient() = 0; // If this client just wraps some other client -- even if it is only *temporarily* wrapping // that other client -- return a reference to the other client, transitively. Otherwise, // return a new reference to *this. virtual void adoptFlowController(kj::Own flowController) { // Called when a PromiseClient resolves to another RpcClient. If streaming calls were // outstanding on the old client, we'd like to keep using the same FlowController on the new // client, so as to keep the flow steady. if (this->flowController == nullptr) { // We don't have any existing flowController so we can adopt this one, yay! this->flowController = kj::mv(flowController); } else { // Apparently, there is an existing flowController. This is an unusual scenario: Apparently // we had two stream capabilities, we were streaming to both of them, and they later // resolved to the same capability. This probably never happens because streaming use cases // normally call for there to be only one client. But, it's certainly possible, and we need // to handle it. We'll do the conservative thing and just make sure that all the calls // finish. This may mean we'll over-buffer temporarily; oh well. connectionState->tasks.add(flowController->waitAllAcked().attach(kj::mv(flowController))); } } // implements ClientHook ----------------------------------------- Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { return newCallNoIntercept(interfaceId, methodId, sizeHint, hints); } Request newCallNoIntercept( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) { if (!connectionState->connection.is()) { return newBrokenRequest(kj::cp(connectionState->connection.get()), sizeHint); } auto request = kj::heap( *connectionState, *connectionState->connection.get(), sizeHint, kj::addRef(*this)); auto callBuilder = request->getCall(); callBuilder.setInterfaceId(interfaceId); callBuilder.setMethodId(methodId); callBuilder.setNoPromisePipelining(hints.noPromisePipelining); callBuilder.setOnlyPromisePipeline(hints.onlyPromisePipeline); auto root = request->getRoot(); return Request(root, kj::mv(request)); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { return callNoIntercept(interfaceId, methodId, kj::mv(context), hints); } VoidPromiseAndPipeline callNoIntercept(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) { // Implement call() by copying params and results messages. auto params = context->getParams(); auto request = newCallNoIntercept(interfaceId, methodId, params.targetSize(), hints); request.set(params); context->releaseParams(); return context->directTailCall(RequestHook::from(kj::mv(request))); } kj::Own addRef() override { return kj::addRef(*this); } const void* getBrand() override { return connectionState.get(); } kj::Own connectionState; kj::Maybe> flowController; // Becomes non-null the first time a streaming call is made on this capability. }; class ImportClient final: public RpcClient { // A ClientHook that wraps an entry in the import table. public: ImportClient(RpcConnectionState& connectionState, ImportId importId, kj::Maybe fd) : RpcClient(connectionState), importId(importId), fd(kj::mv(fd)) {} ~ImportClient() noexcept(false) { unwindDetector.catchExceptionsIfUnwinding([&]() { // Remove self from the import table, if the table is still pointing at us. KJ_IF_MAYBE(import, connectionState->imports.find(importId)) { KJ_IF_MAYBE(i, import->importClient) { if (i == this) { connectionState->imports.erase(importId); } } } // Send a message releasing our remote references. if (remoteRefcount > 0 && connectionState->connection.is()) { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint()); rpc::Release::Builder builder = message->getBody().initAs().initRelease(); builder.setId(importId); builder.setReferenceCount(remoteRefcount); message->send(); } }); } void setFdIfMissing(kj::Maybe newFd) { if (fd == nullptr) { fd = kj::mv(newFd); } } void addRemoteRef() { // Add a new RemoteRef and return a new ref to this client representing it. ++remoteRefcount; } kj::Maybe writeDescriptor(rpc::CapDescriptor::Builder descriptor, kj::Vector& fds) override { descriptor.setReceiverHosted(importId); return nullptr; } kj::Maybe> writeTarget( rpc::MessageTarget::Builder target) override { target.setImportedCap(importId); return nullptr; } kj::Own getInnermostClient() override { return kj::addRef(*this); } // implements ClientHook ----------------------------------------- kj::Maybe getResolved() override { return nullptr; } kj::Maybe>> whenMoreResolved() override { return nullptr; } kj::Maybe getFd() override { return fd.map([](auto& f) { return f.get(); }); } private: ImportId importId; kj::Maybe fd; uint remoteRefcount = 0; // Number of times we've received this import from the peer. kj::UnwindDetector unwindDetector; }; class PipelineClient final: public RpcClient { // A ClientHook representing a pipelined promise. Always wrapped in PromiseClient. public: PipelineClient(RpcConnectionState& connectionState, kj::Own&& questionRef, kj::Array&& ops) : RpcClient(connectionState), questionRef(kj::mv(questionRef)), ops(kj::mv(ops)) {} kj::Maybe writeDescriptor(rpc::CapDescriptor::Builder descriptor, kj::Vector& fds) override { auto promisedAnswer = descriptor.initReceiverAnswer(); promisedAnswer.setQuestionId(questionRef->getId()); promisedAnswer.adoptTransform(fromPipelineOps( Orphanage::getForMessageContaining(descriptor), ops)); return nullptr; } kj::Maybe> writeTarget( rpc::MessageTarget::Builder target) override { auto builder = target.initPromisedAnswer(); builder.setQuestionId(questionRef->getId()); builder.adoptTransform(fromPipelineOps(Orphanage::getForMessageContaining(builder), ops)); return nullptr; } kj::Own getInnermostClient() override { return kj::addRef(*this); } // implements ClientHook ----------------------------------------- kj::Maybe getResolved() override { return nullptr; } kj::Maybe>> whenMoreResolved() override { return nullptr; } kj::Maybe getFd() override { return nullptr; } private: kj::Own questionRef; kj::Array ops; }; class PromiseClient final: public RpcClient { // A ClientHook that initially wraps one client (in practice, an ImportClient or a // PipelineClient) and then, later on, redirects to some other client. public: PromiseClient(RpcConnectionState& connectionState, kj::Own initial, kj::Promise> eventual, kj::Maybe importId) : RpcClient(connectionState), cap(kj::mv(initial)), importId(importId), fork(eventual.then( [this](kj::Own&& resolution) { return resolve(kj::mv(resolution)); }, [this](kj::Exception&& exception) { return resolve(newBrokenCap(kj::mv(exception))); }).catch_([&](kj::Exception&& e) { // Make any exceptions thrown from resolve() go to the connection's TaskSet which // will cause the connection to be terminated. connectionState.tasks.add(kj::cp(e)); return newBrokenCap(kj::mv(e)); }).fork()) {} // Create a client that starts out forwarding all calls to `initial` but, once `eventual` // resolves, will forward there instead. ~PromiseClient() noexcept(false) { KJ_IF_MAYBE(id, importId) { // This object is representing an import promise. That means the import table may still // contain a pointer back to it. Remove that pointer. Note that we have to verify that // the import still exists and the pointer still points back to this object because this // object may actually outlive the import. KJ_IF_MAYBE(import, connectionState->imports.find(*id)) { KJ_IF_MAYBE(c, import->appClient) { if (c == this) { import->appClient = nullptr; } } } } } kj::Maybe writeDescriptor(rpc::CapDescriptor::Builder descriptor, kj::Vector& fds) override { receivedCall = true; return connectionState->writeDescriptor(*cap, descriptor, fds); } kj::Maybe> writeTarget( rpc::MessageTarget::Builder target) override { receivedCall = true; return connectionState->writeTarget(*cap, target); } kj::Own getInnermostClient() override { receivedCall = true; return connectionState->getInnermostClient(*cap); } void adoptFlowController(kj::Own flowController) override { if (cap->getBrand() == connectionState.get()) { // Pass the flow controller on to our inner cap. kj::downcast(*cap).adoptFlowController(kj::mv(flowController)); } else { // We resolved to a capability that isn't another RPC capability. We should simply make // sure that all the calls complete. connectionState->tasks.add(flowController->waitAllAcked().attach(kj::mv(flowController))); } } // implements ClientHook ----------------------------------------- Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { receivedCall = true; // IMPORTANT: We must call our superclass's version of newCall(), NOT cap->newCall(), because // the Request object we create needs to check at send() time whether the promise has // resolved and, if so, redirect to the new target. return RpcClient::newCall(interfaceId, methodId, sizeHint, hints); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { receivedCall = true; return cap->call(interfaceId, methodId, kj::mv(context), hints); } kj::Maybe getResolved() override { if (isResolved()) { return *cap; } else { return nullptr; } } kj::Maybe>> whenMoreResolved() override { return fork.addBranch(); } kj::Maybe getFd() override { if (isResolved()) { return cap->getFd(); } else { // In theory, before resolution, the ImportClient for the promise could have an FD // attached, if the promise itself was presented with an attached FD. However, we can't // really return that one here because it may be closed when we get the Resolve message // later. In theory we could have the PromiseClient itself take ownership of an FD that // arrived attached to a promise cap, but the use case for that is questionable. I'm // keeping it simple for now. return nullptr; } } private: kj::Own cap; kj::Maybe importId; kj::ForkedPromise> fork; bool receivedCall = false; enum { UNRESOLVED, // Not resolved at all yet. REMOTE, // Remote promise resolved to a remote settled capability (or null/error). REFLECTED, // Remote promise resolved to one of our own exports. MERGED, // Remote promise resolved to another remote promise which itself wasn't resolved yet, so we // merged them. In this case, `cap` is guaranteed to point to another PromiseClient. BROKEN // Resolved to null or error. } resolutionType = UNRESOLVED; inline bool isResolved() { return resolutionType != UNRESOLVED; } kj::Promise> resolve(kj::Own replacement) { KJ_DASSERT(!isResolved()); const void* replacementBrand = replacement->getBrand(); bool isSameConnection = replacementBrand == connectionState.get(); if (isSameConnection) { // We resolved to some other RPC capability hosted by the same peer. KJ_IF_MAYBE(promise, replacement->whenMoreResolved()) { // We resolved to another remote promise. If *that* promise eventually resolves back // to us, we'll need a disembargo. Possibilities: // 1. The other promise hasn't resolved at all yet. In that case we can simply set its // `receivedCall` flag and let it handle the disembargo later. // 2. The other promise has received a Resolve message and decided to initiate a // disembargo which it is still waiting for. In that case we will certainly also need // a disembargo for the same reason that the other promise did. And, we can't simply // wait for their disembargo; we need to start a new one of our own. // 3. The other promise has resolved already (with or without a disembargo). In this // case we should treat it as if we resolved directly to the other promise's result, // possibly requiring a disembargo under the same conditions. // We know the other object is a PromiseClient because it's the only ClientHook // type in the RPC implementation which returns non-null for `whenMoreResolved()`. PromiseClient* other = &kj::downcast(*replacement); while (other->resolutionType == MERGED) { // There's no need to resolve to a thing that's just going to resolve to another thing. replacement = other->cap->addRef(); other = &kj::downcast(*replacement); // Note that replacementBrand is unchanged since we'd only merge with other // PromiseClients on the same connection. KJ_DASSERT(replacement->getBrand() == replacementBrand); } if (other->isResolved()) { // The other capability resolved already. If it determined that it resolved as // reflected, then we determine the same. resolutionType = other->resolutionType; } else { // The other capability hasn't resolved yet, so we can safely merge with it and do a // single combined disembargo if needed later. other->receivedCall = other->receivedCall || receivedCall; resolutionType = MERGED; } } else { resolutionType = REMOTE; } } else { if (replacementBrand == &ClientHook::NULL_CAPABILITY_BRAND || replacementBrand == &ClientHook::BROKEN_CAPABILITY_BRAND) { // We don't consider null or broken capabilities as "reflected" because they may have // been communicated to us literally as a null pointer or an exception on the wire, // rather than as a reference to one of our exports, in which case a disembargo won't // work. But also, call ordering is completely irrelevant with these so there's no need // to disembargo anyway. resolutionType = BROKEN; } else { resolutionType = REFLECTED; } } // Every branch above ends by setting resolutionType to something other than UNRESOLVED. KJ_DASSERT(isResolved()); // If the original capability was used for streaming calls, it will have a // `flowController` that might still be shepherding those calls. We'll need make sure that // it doesn't get thrown away. Note that we know that *cap is an RpcClient because resolve() // is only called once and our constructor required that the initial capability is an // RpcClient. KJ_IF_MAYBE(f, kj::downcast(*cap).flowController) { if (isSameConnection) { // The new target is on the same connection. It would make a lot of sense to keep using // the same flow controller if possible. kj::downcast(*replacement).adoptFlowController(kj::mv(*f)); } else { // The new target is something else. The best we can do is wait for the controller to // drain. New calls will be flow-controlled in a new way without knowing about the old // controller. connectionState->tasks.add(f->get()->waitAllAcked().attach(kj::mv(*f))); } } if (resolutionType == REFLECTED && receivedCall && connectionState->connection.is()) { // The new capability is hosted locally, not on the remote machine. And, we had made calls // to the promise. We need to make sure those calls echo back to us before we allow new // calls to go directly to the local capability, so we need to set a local embargo and send // a `Disembargo` to echo through the peer. auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint() + MESSAGE_TARGET_SIZE_HINT); auto disembargo = message->getBody().initAs().initDisembargo(); { auto redirect = connectionState->writeTarget(*cap, disembargo.initTarget()); KJ_ASSERT(redirect == nullptr, "Original promise target should always be from this RPC connection."); } EmbargoId embargoId; Embargo& embargo = connectionState->embargoes.next(embargoId); disembargo.getContext().setSenderLoopback(embargoId); auto paf = kj::newPromiseAndFulfiller(); embargo.fulfiller = kj::mv(paf.fulfiller); // Make a promise which resolves to `replacement` as soon as the `Disembargo` comes back. auto embargoPromise = paf.promise.then([replacement = kj::mv(replacement)]() mutable { return kj::mv(replacement); }); // We need to queue up calls in the meantime, so we'll resolve ourselves to a local promise // client instead. replacement = newLocalPromiseClient(kj::mv(embargoPromise)); // Send the `Disembargo`. message->send(); } cap = replacement->addRef(); return kj::mv(replacement); } }; kj::Maybe writeDescriptor(ClientHook& cap, rpc::CapDescriptor::Builder descriptor, kj::Vector& fds) { // Write a descriptor for the given capability. // Find the innermost wrapped capability. ClientHook* inner = ∩ for (;;) { KJ_IF_MAYBE(resolved, inner->getResolved()) { inner = resolved; } else { break; } } KJ_IF_MAYBE(fd, inner->getFd()) { descriptor.setAttachedFd(fds.size()); fds.add(kj::mv(*fd)); } if (inner->getBrand() == this) { return kj::downcast(*inner).writeDescriptor(descriptor, fds); } else { auto iter = exportsByCap.find(inner); if (iter != exportsByCap.end()) { // We've already seen and exported this capability before. Just up the refcount. auto& exp = KJ_ASSERT_NONNULL(exports.find(iter->second)); ++exp.refcount; if (exp.resolveOp == nullptr) { descriptor.setSenderHosted(iter->second); } else { descriptor.setSenderPromise(iter->second); } return iter->second; } else { // This is the first time we've seen this capability. ExportId exportId; auto& exp = exports.next(exportId); exportsByCap[inner] = exportId; exp.refcount = 1; exp.clientHook = inner->addRef(); KJ_IF_MAYBE(wrapped, inner->whenMoreResolved()) { // This is a promise. Arrange for the `Resolve` message to be sent later. exp.resolveOp = resolveExportedPromise(exportId, kj::mv(*wrapped)); descriptor.setSenderPromise(exportId); } else { descriptor.setSenderHosted(exportId); } return exportId; } } } kj::Array writeDescriptors(kj::ArrayPtr>> capTable, rpc::Payload::Builder payload, kj::Vector& fds) { if (capTable.size() == 0) { // Calling initCapTable(0) will still allocate a 1-word tag, which we'd like to avoid... return nullptr; } auto capTableBuilder = payload.initCapTable(capTable.size()); kj::Vector exports(capTable.size()); for (uint i: kj::indices(capTable)) { KJ_IF_MAYBE(cap, capTable[i]) { KJ_IF_MAYBE(exportId, writeDescriptor(**cap, capTableBuilder[i], fds)) { exports.add(*exportId); } } else { capTableBuilder[i].setNone(); } } return exports.releaseAsArray(); } kj::Maybe> writeTarget(ClientHook& cap, rpc::MessageTarget::Builder target) { // If calls to the given capability should pass over this connection, fill in `target` // appropriately for such a call and return nullptr. Otherwise, return a `ClientHook` to which // the call should be forwarded; the caller should then delegate the call to that `ClientHook`. // // The main case where this ends up returning non-null is if `cap` is a promise that has // recently resolved. The application might have started building a request before the promise // resolved, and so the request may have been built on the assumption that it would be sent over // this network connection, but then the promise resolved to point somewhere else before the // request was sent. Now the request has to be redirected to the new target instead. if (cap.getBrand() == this) { return kj::downcast(cap).writeTarget(target); } else { return cap.addRef(); } } kj::Own getInnermostClient(ClientHook& client) { ClientHook* ptr = &client; for (;;) { KJ_IF_MAYBE(inner, ptr->getResolved()) { ptr = inner; } else { break; } } if (ptr->getBrand() == this) { return kj::downcast(*ptr).getInnermostClient(); } else { return ptr->addRef(); } } kj::Promise resolveExportedPromise( ExportId exportId, kj::Promise>&& promise) { // Implements exporting of a promise. The promise has been exported under the given ID, and is // to eventually resolve to the ClientHook produced by `promise`. This method waits for that // resolve to happen and then sends the appropriate `Resolve` message to the peer. return promise.then( [this,exportId](kj::Own&& resolution) -> kj::Promise { // Successful resolution. KJ_ASSERT(connection.is(), "Resolving export should have been canceled on disconnect.") { return kj::READY_NOW; } // Get the innermost ClientHook backing the resolved client. This includes traversing // PromiseClients that haven't resolved yet to their underlying ImportClient or // PipelineClient, so that we get a remote promise that might resolve later. This is // important to make sure that if the peer sends a `Disembargo` back to us, it bounces back // correctly instead of going to the result of some future resolution. See the documentation // for `Disembargo` in `rpc.capnp`. resolution = getInnermostClient(*resolution); // Update the export table to point at this object instead. We know that our entry in the // export table is still live because when it is destroyed the asynchronous resolution task // (i.e. this code) is canceled. auto& exp = KJ_ASSERT_NONNULL(exports.find(exportId)); exportsByCap.erase(exp.clientHook); exp.clientHook = kj::mv(resolution); if (exp.clientHook->getBrand() != this) { // We're resolving to a local capability. If we're resolving to a promise, we might be // able to reuse our export table entry and avoid sending a message. KJ_IF_MAYBE(promise, exp.clientHook->whenMoreResolved()) { // We're replacing a promise with another local promise. In this case, we might actually // be able to just reuse the existing export table entry to represent the new promise -- // unless it already has an entry. Let's check. auto insertResult = exportsByCap.insert(std::make_pair(exp.clientHook.get(), exportId)); if (insertResult.second) { // The new promise was not already in the table, therefore the existing export table // entry has now been repurposed to represent it. There is no need to send a resolve // message at all. We do, however, have to start resolving the next promise. return resolveExportedPromise(exportId, kj::mv(*promise)); } } } // OK, we have to send a `Resolve` message. auto message = connection.get()->newOutgoingMessage( messageSizeHint() + sizeInWords() + 16); auto resolve = message->getBody().initAs().initResolve(); resolve.setPromiseId(exportId); kj::Vector fds; writeDescriptor(*exp.clientHook, resolve.initCap(), fds); message->setFds(fds.releaseAsArray()); message->send(); return kj::READY_NOW; }, [this,exportId](kj::Exception&& exception) { // send error resolution auto message = connection.get()->newOutgoingMessage( messageSizeHint() + exceptionSizeHint(exception) + 8); auto resolve = message->getBody().initAs().initResolve(); resolve.setPromiseId(exportId); fromException(exception, resolve.initException()); message->send(); }).eagerlyEvaluate([this](kj::Exception&& exception) { // Put the exception on the TaskSet which will cause the connection to be terminated. tasks.add(kj::mv(exception)); }); } void fromException(const kj::Exception& exception, rpc::Exception::Builder builder) { _::fromException(exception, builder, traceEncoder); } // ===================================================================================== // Interpreting CapDescriptor kj::Own import(ImportId importId, bool isPromise, kj::Maybe fd) { // Receive a new import. auto& import = imports[importId]; kj::Own importClient; // Create the ImportClient, or if one already exists, use it. KJ_IF_MAYBE(c, import.importClient) { importClient = kj::addRef(*c); // If the same import is introduced multiple times, and it is missing an FD the first time, // but it has one on a later attempt, we want to attach the later one. This could happen // because the first introduction was part of a message that had too many other FDs and went // over the per-message limit. Perhaps the protocol design is such that this other message // doesn't really care if the FDs are transferred or not, but the later message really does // care; it would be bad if the previous message blocked later messages from delivering the // FD just because it happened to reference the same capability. importClient->setFdIfMissing(kj::mv(fd)); } else { importClient = kj::refcounted(*this, importId, kj::mv(fd)); import.importClient = *importClient; } // We just received a copy of this import ID, so the remote refcount has gone up. importClient->addRemoteRef(); if (isPromise) { // We need to construct a PromiseClient around this import, if we haven't already. KJ_IF_MAYBE(c, import.appClient) { // Use the existing one. return kj::addRef(*c); } else { // Create a promise for this import's resolution. auto paf = kj::newPromiseAndFulfiller>(); import.promiseFulfiller = kj::mv(paf.fulfiller); // Make sure the import is not destroyed while this promise exists. paf.promise = paf.promise.attach(kj::addRef(*importClient)); // Create a PromiseClient around it and return it. auto result = kj::refcounted( *this, kj::mv(importClient), kj::mv(paf.promise), importId); import.appClient = *result; return kj::mv(result); } } else { import.appClient = *importClient; return kj::mv(importClient); } } class TribbleRaceBlocker: public ClientHook, public kj::Refcounted { // Hack to work around a problem that arises during the Tribble 4-way Race Condition as // described in rpc.capnp in the documentation for the `Disembargo` message. // // Consider a remote promise that is resolved by a `Resolve` message. PromiseClient::resolve() // is eventually called and given the `ClientHook` for the resolution. Imagine that the // `ClientHook` it receives turns out to be an `ImportClient`. There are two ways this could // have happened: // // 1. The `Resolve` message contained a `CapDescriptor` of type `senderHosted`, naming an entry // in the sender's export table, and the `ImportClient` refers to the corresponding slot on // the receiver's import table. In this case, no embargo is needed, because messages to the // resolved location traverse the same path as messages to the promise would have. // // 2. The `Resolve` message contained a `CapDescriptor` of type `receiverHosted`, naming an // entry in the receiver's export table. That entry just happened to contain an // `ImportClient` referring back to the sender. This specifically happens when the entry // in question had previously itself referred to a promise, and that promise has since // resolved to a remote capability, at which point the export table entry was replaced by // the appropriate `ImportClient` representing that. Presumably, the peer *did not yet know* // about this resolution, which is why it sent a `receiverHosted` pointing to something that // reflects back to the sender, rather than sending `senderHosted` in the first place. // // In this case, an embargo *is* required, because peer may still be reflecting messages // sent to this promise back to us. In fact, the peer *must* continue reflecting messages, // even when it eventually learns that the eventual destination is one of its own // capabilities, due to the Tribble 4-way Race Condition rule. // // Since this case requires an embargo, somehow PromiseClient::resolve() must be able to // distinguish it from the case (1). One solution would be for us to pass some extra flag // all the way from where the `Resolve` messages is received to `PromiseClient::resolve()`. // That solution is reasonably easy in the `Resolve` case, but gets notably more difficult // in the case of `Return`s, which also resolve promises and are subject to all the same // problems. In the case of a `Return`, some non-RPC-specific code is involved in the // resolution, making it harder to pass along a flag. // // Instead, we use this hack: When we read an entry in the export table and discover that // it actually contains an `ImportClient` or a `PipelineClient` reflecting back over our // own connection, then we wrap it in a `TribbleRaceBlocker`. This wrapper prevents // `PromiseClient` from recognizing the capability as being remote, so it instead treats it // as local. That causes it to set up an embargo as desired. // // TODO(perf): This actually blocks further promise resolution in the case where the // ImportClient or PipelineClient itself ends up being yet another promise that resolves // back over the connection again. What we probably really need to do here is, instead of // placing `ImportClient` or `PipelineClient` on the export table, place a special type there // that both knows what to do with future incoming messages to that export ID, but also knows // what to do when that export is the subject of a `Resolve`. public: TribbleRaceBlocker(kj::Own inner): inner(kj::mv(inner)) {} Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { return inner->newCall(interfaceId, methodId, sizeHint, hints); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { return inner->call(interfaceId, methodId, kj::mv(context), hints); } kj::Maybe getResolved() override { // We always wrap either PipelineClient or ImportClient, both of which return null for this // anyway. return nullptr; } kj::Maybe>> whenMoreResolved() override { // We always wrap either PipelineClient or ImportClient, both of which return null for this // anyway. return nullptr; } kj::Own addRef() override { return kj::addRef(*this); } const void* getBrand() override { return nullptr; } kj::Maybe getFd() override { return inner->getFd(); } private: kj::Own inner; }; kj::Maybe> receiveCap(rpc::CapDescriptor::Reader descriptor, kj::ArrayPtr fds) { uint fdIndex = descriptor.getAttachedFd(); kj::Maybe fd; if (fdIndex < fds.size() && fds[fdIndex] != nullptr) { fd = kj::mv(fds[fdIndex]); } switch (descriptor.which()) { case rpc::CapDescriptor::NONE: return nullptr; case rpc::CapDescriptor::SENDER_HOSTED: return import(descriptor.getSenderHosted(), false, kj::mv(fd)); case rpc::CapDescriptor::SENDER_PROMISE: return import(descriptor.getSenderPromise(), true, kj::mv(fd)); case rpc::CapDescriptor::RECEIVER_HOSTED: KJ_IF_MAYBE(exp, exports.find(descriptor.getReceiverHosted())) { auto result = exp->clientHook->addRef(); if (result->getBrand() == this) { result = kj::refcounted(kj::mv(result)); } return kj::mv(result); } else { return newBrokenCap("invalid 'receiverHosted' export ID"); } case rpc::CapDescriptor::RECEIVER_ANSWER: { auto promisedAnswer = descriptor.getReceiverAnswer(); KJ_IF_MAYBE(answer, answers.find(promisedAnswer.getQuestionId())) { if (answer->active) { KJ_IF_MAYBE(pipeline, answer->pipeline) { KJ_IF_MAYBE(ops, toPipelineOps(promisedAnswer.getTransform())) { auto result = pipeline->get()->getPipelinedCap(*ops); if (result->getBrand() == this) { result = kj::refcounted(kj::mv(result)); } return kj::mv(result); } else { return newBrokenCap("unrecognized pipeline ops"); } } } } return newBrokenCap("invalid 'receiverAnswer'"); } case rpc::CapDescriptor::THIRD_PARTY_HOSTED: // We don't support third-party caps, so use the vine instead. return import(descriptor.getThirdPartyHosted().getVineId(), false, kj::mv(fd)); default: KJ_FAIL_REQUIRE("unknown CapDescriptor type") { break; } return newBrokenCap("unknown CapDescriptor type"); } } kj::Array>> receiveCaps(List::Reader capTable, kj::ArrayPtr fds) { auto result = kj::heapArrayBuilder>>(capTable.size()); for (auto cap: capTable) { result.add(receiveCap(cap, fds)); } return result.finish(); } // ===================================================================================== // RequestHook/PipelineHook/ResponseHook implementations class QuestionRef: public kj::Refcounted { // A reference to an entry on the question table. Used to detect when the `Finish` message // can be sent. public: inline QuestionRef( RpcConnectionState& connectionState, QuestionId id, kj::Maybe>>>> fulfiller) : connectionState(kj::addRef(connectionState)), id(id), fulfiller(kj::mv(fulfiller)) {} ~QuestionRef() noexcept { // Contrary to KJ style, we declare this destructor `noexcept` because if anything in here // throws (without being caught) we're probably in pretty bad shape and going to be crashing // later anyway. Better to abort now. KJ_IF_MAYBE(c, connectionState) { auto& connectionState = *c; auto& question = KJ_ASSERT_NONNULL( connectionState->questions.find(id), "Question ID no longer on table?"); // Send the "Finish" message (if the connection is not already broken). if (connectionState->connection.is() && !question.skipFinish) { KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint()); auto builder = message->getBody().getAs().initFinish(); builder.setQuestionId(id); // If we're still awaiting a return, then this request is being canceled, and we're going // to ignore any capabilities in the return message, so set releaseResultCaps true. If we // already received the return, then we've already built local proxies for the caps and // will send Release messages when those are destroyed. builder.setReleaseResultCaps(question.isAwaitingReturn); // Let the peer know we don't have the early cancellation bug. builder.setRequireEarlyCancellationWorkaround(false); message->send(); })) { connectionState->tasks.add(kj::mv(*e)); } } // Check if the question has returned and, if so, remove it from the table. // Remove question ID from the table. Must do this *after* sending `Finish` to ensure that // the ID is not re-allocated before the `Finish` message can be sent. if (question.isAwaitingReturn) { // Still waiting for return, so just remove the QuestionRef pointer from the table. question.selfRef = nullptr; } else { // Call has already returned, so we can now remove it from the table. connectionState->questions.erase(id, question); } } } inline QuestionId getId() const { return id; } void fulfill(kj::Own&& response) { KJ_IF_MAYBE(f, fulfiller) { f->get()->fulfill(kj::mv(response)); } } void fulfill(kj::Promise>&& promise) { KJ_IF_MAYBE(f, fulfiller) { f->get()->fulfill(kj::mv(promise)); } } void reject(kj::Exception&& exception) { KJ_IF_MAYBE(f, fulfiller) { f->get()->reject(kj::mv(exception)); } } void disconnect() { connectionState = nullptr; } private: kj::Maybe> connectionState; QuestionId id; kj::Maybe>>>> fulfiller; }; class RpcRequest final: public RequestHook { public: RpcRequest(RpcConnectionState& connectionState, VatNetworkBase::Connection& connection, kj::Maybe sizeHint, kj::Own&& target) : connectionState(kj::addRef(connectionState)), target(kj::mv(target)), message(connection.newOutgoingMessage( firstSegmentSize(sizeHint, messageSizeHint() + sizeInWords() + MESSAGE_TARGET_SIZE_HINT))), callBuilder(message->getBody().getAs().initCall()), paramsBuilder(capTable.imbue(callBuilder.getParams().getContent())) {} inline AnyPointer::Builder getRoot() { return paramsBuilder; } inline rpc::Call::Builder getCall() { return callBuilder; } RemotePromise send() override { if (!connectionState->connection.is()) { // Connection is broken. // TODO(bug): Seems like we should check for redirect before this? const kj::Exception& e = connectionState->connection.get(); return RemotePromise( kj::Promise>(kj::cp(e)), AnyPointer::Pipeline(newBrokenPipeline(kj::cp(e)))); } KJ_IF_MAYBE(redirect, target->writeTarget(callBuilder.getTarget())) { // Whoops, this capability has been redirected while we were building the request! // We'll have to make a new request and do a copy. Ick. auto replacement = redirect->get()->newCall( callBuilder.getInterfaceId(), callBuilder.getMethodId(), paramsBuilder.targetSize(), callHintsFromReader(callBuilder)); replacement.set(paramsBuilder); return replacement.send(); } else { bool noPromisePipelining = callBuilder.getNoPromisePipelining(); auto sendResult = sendInternal(false); kj::Own pipeline; if (noPromisePipelining) { pipeline = getDisabledPipeline(); } else { auto forkedPromise = sendResult.promise.fork(); // The pipeline must get notified of resolution before the app does to maintain ordering. pipeline = kj::refcounted( *connectionState, kj::mv(sendResult.questionRef), forkedPromise.addBranch()); sendResult.promise = forkedPromise.addBranch(); } auto appPromise = sendResult.promise.then( [=](kj::Own&& response) { auto reader = response->getResults(); return Response(reader, kj::mv(response)); }); return RemotePromise( kj::mv(appPromise), AnyPointer::Pipeline(kj::mv(pipeline))); } } kj::Promise sendStreaming() override { if (!connectionState->connection.is()) { // Connection is broken. // TODO(bug): Seems like we should check for redirect before this? return kj::cp(connectionState->connection.get()); } KJ_IF_MAYBE(redirect, target->writeTarget(callBuilder.getTarget())) { // Whoops, this capability has been redirected while we were building the request! // We'll have to make a new request and do a copy. Ick. auto replacement = redirect->get()->newCall( callBuilder.getInterfaceId(), callBuilder.getMethodId(), paramsBuilder.targetSize(), callHintsFromReader(callBuilder)); replacement.set(paramsBuilder); return RequestHook::from(kj::mv(replacement))->sendStreaming(); } else { return sendStreamingInternal(false); } } AnyPointer::Pipeline sendForPipeline() override { if (!connectionState->connection.is()) { // Connection is broken. // TODO(bug): Seems like we should check for redirect before this? const kj::Exception& e = connectionState->connection.get(); return AnyPointer::Pipeline(newBrokenPipeline(kj::cp(e))); } KJ_IF_MAYBE(redirect, target->writeTarget(callBuilder.getTarget())) { // Whoops, this capability has been redirected while we were building the request! // We'll have to make a new request and do a copy. Ick. auto replacement = redirect->get()->newCall( callBuilder.getInterfaceId(), callBuilder.getMethodId(), paramsBuilder.targetSize(), callHintsFromReader(callBuilder)); replacement.set(paramsBuilder); return replacement.sendForPipeline(); } else if (connectionState->gotReturnForHighQuestionId) { // Peer doesn't implement our hints. Fall back to a regular send(). return send(); } else { auto questionRef = sendForPipelineInternal(); kj::Own pipeline = kj::refcounted( *connectionState, kj::mv(questionRef)); return AnyPointer::Pipeline(kj::mv(pipeline)); } } struct TailInfo { QuestionId questionId; kj::Promise promise; kj::Own pipeline; }; kj::Maybe tailSend() { // Send the request as a tail call. // // Returns null if for some reason a tail call is not possible and the caller should fall // back to using send() and copying the response. SendInternalResult sendResult; if (!connectionState->connection.is()) { // Disconnected; fall back to a regular send() which will fail appropriately. return nullptr; } KJ_IF_MAYBE(redirect, target->writeTarget(callBuilder.getTarget())) { // Whoops, this capability has been redirected while we were building the request! // Fall back to regular send(). return nullptr; } else { sendResult = sendInternal(true); } auto promise = sendResult.promise.then([](kj::Own&& response) { // Response should be null if `Return` handling code is correct. KJ_ASSERT(!response) { break; } }); QuestionId questionId = sendResult.questionRef->getId(); kj::Own pipeline; bool noPromisePipelining = callBuilder.getNoPromisePipelining(); if (noPromisePipelining) { pipeline = getDisabledPipeline(); } else { pipeline = kj::refcounted(*connectionState, kj::mv(sendResult.questionRef)); } return TailInfo { questionId, kj::mv(promise), kj::mv(pipeline) }; } const void* getBrand() override { return connectionState.get(); } private: kj::Own connectionState; kj::Own target; kj::Own message; BuilderCapabilityTable capTable; rpc::Call::Builder callBuilder; AnyPointer::Builder paramsBuilder; struct SendInternalResult { kj::Own questionRef; kj::Promise> promise = nullptr; }; struct SetupSendResult: public SendInternalResult { QuestionId questionId; Question& question; SetupSendResult(SendInternalResult&& super, QuestionId questionId, Question& question) : SendInternalResult(kj::mv(super)), questionId(questionId), question(question) {} // TODO(cleanup): This constructor is implicit in C++17. }; SetupSendResult setupSend(bool isTailCall) { // Build the cap table. kj::Vector fds; auto exports = connectionState->writeDescriptors( capTable.getTable(), callBuilder.getParams(), fds); message->setFds(fds.releaseAsArray()); // Init the question table. Do this after writing descriptors to avoid interference. QuestionId questionId; auto& question = connectionState->questions.next(questionId); question.isAwaitingReturn = true; question.paramExports = kj::mv(exports); question.isTailCall = isTailCall; // Make the QuentionRef and result promise. SendInternalResult result; auto paf = kj::newPromiseAndFulfiller>>(); result.questionRef = kj::refcounted( *connectionState, questionId, kj::mv(paf.fulfiller)); question.selfRef = *result.questionRef; result.promise = paf.promise.attach(kj::addRef(*result.questionRef)); return { kj::mv(result), questionId, question }; } SendInternalResult sendInternal(bool isTailCall) { auto result = setupSend(isTailCall); // Finish and send. callBuilder.setQuestionId(result.questionId); if (isTailCall) { callBuilder.getSendResultsTo().setYourself(); } KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { KJ_CONTEXT("sending RPC call", callBuilder.getInterfaceId(), callBuilder.getMethodId()); message->send(); })) { // We can't safely throw the exception from here since we've already modified the question // table state. We'll have to reject the promise instead. // TODO(bug): Attempts to use the pipeline will end up sending a request referencing a // bogus question ID. Can we rethrow after doing the appropriate cleanup, so the pipeline // is never created? See the approach in sendForPipelineInternal() below. result.question.isAwaitingReturn = false; result.question.skipFinish = true; connectionState->releaseExports(result.question.paramExports); result.questionRef->reject(kj::mv(*exception)); } // Send and return. return kj::mv(result); } kj::Promise sendStreamingInternal(bool isTailCall) { auto setup = setupSend(isTailCall); // Finish and send. callBuilder.setQuestionId(setup.questionId); if (isTailCall) { callBuilder.getSendResultsTo().setYourself(); } kj::Promise flowPromise = nullptr; KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { KJ_CONTEXT("sending RPC call", callBuilder.getInterfaceId(), callBuilder.getMethodId()); RpcFlowController* flow; KJ_IF_MAYBE(f, target->flowController) { flow = *f; } else { flow = target->flowController.emplace( connectionState->connection.get()->newStream()); } flowPromise = flow->send(kj::mv(message), setup.promise.ignoreResult()); })) { // We can't safely throw the exception from here since we've already modified the question // table state. We'll have to reject the promise instead. setup.question.isAwaitingReturn = false; setup.question.skipFinish = true; setup.questionRef->reject(kj::cp(*exception)); return kj::mv(*exception); } return kj::mv(flowPromise); } kj::Own sendForPipelineInternal() { // Since must of setupSend() is subtly different for this case, we don't reuse it. // Build the cap table. kj::Vector fds; auto exports = connectionState->writeDescriptors( capTable.getTable(), callBuilder.getParams(), fds); message->setFds(fds.releaseAsArray()); if (exports.size() > 0) { connectionState->sentCapabilitiesInPipelineOnlyCall = true; } // Init the question table. Do this after writing descriptors to avoid interference. QuestionId questionId; auto& question = connectionState->questions.nextHigh(questionId); question.isAwaitingReturn = false; // No Return needed question.paramExports = kj::mv(exports); question.isTailCall = false; // Make the QuentionRef and result promise. auto questionRef = kj::refcounted(*connectionState, questionId, nullptr); question.selfRef = *questionRef; // If sending throws, we'll need to fix up the state a little... KJ_ON_SCOPE_FAILURE({ question.skipFinish = true; connectionState->releaseExports(question.paramExports); }); // Finish and send. callBuilder.setQuestionId(questionId); callBuilder.setOnlyPromisePipeline(true); KJ_CONTEXT("sending RPC call", callBuilder.getInterfaceId(), callBuilder.getMethodId()); message->send(); return kj::mv(questionRef); } }; class RpcPipeline final: public PipelineHook, public kj::Refcounted { public: RpcPipeline(RpcConnectionState& connectionState, kj::Own&& questionRef, kj::Promise>&& redirectLaterParam) : connectionState(kj::addRef(connectionState)), redirectLater(redirectLaterParam.fork()), resolveSelfPromise(KJ_ASSERT_NONNULL(redirectLater).addBranch().then( [this](kj::Own&& response) { resolve(kj::mv(response)); }, [this](kj::Exception&& exception) { resolve(kj::mv(exception)); }).eagerlyEvaluate([&](kj::Exception&& e) { // Make any exceptions thrown from resolve() go to the connection's TaskSet which // will cause the connection to be terminated. connectionState.tasks.add(kj::mv(e)); })) { // Construct a new RpcPipeline. state.init(kj::mv(questionRef)); } RpcPipeline(RpcConnectionState& connectionState, kj::Own&& questionRef) : connectionState(kj::addRef(connectionState)), resolveSelfPromise(nullptr) { // Construct a new RpcPipeline that is never expected to resolve. state.init(kj::mv(questionRef)); } // implements PipelineHook --------------------------------------- kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { auto copy = kj::heapArrayBuilder(ops.size()); for (auto& op: ops) { copy.add(op); } return getPipelinedCap(copy.finish()); } kj::Own getPipelinedCap(kj::Array&& ops) override { return clientMap.findOrCreate(ops.asPtr(), [&]() { if (state.is()) { // Wrap a PipelineClient in a PromiseClient. auto pipelineClient = kj::refcounted( *connectionState, kj::addRef(*state.get()), kj::heapArray(ops.asPtr())); KJ_IF_MAYBE(r, redirectLater) { auto resolutionPromise = r->addBranch().then( [ops = kj::heapArray(ops.asPtr())](kj::Own&& response) { return response->getResults().getPipelinedCap(kj::mv(ops)); }); return kj::HashMap, kj::Own>::Entry { kj::mv(ops), kj::refcounted( *connectionState, kj::mv(pipelineClient), kj::mv(resolutionPromise), nullptr) }; } else { // Oh, this pipeline will never get redirected, so just return the PipelineClient. return kj::HashMap, kj::Own>::Entry { kj::mv(ops), kj::mv(pipelineClient) }; } } else if (state.is()) { auto pipelineClient = state.get()->getResults().getPipelinedCap(ops); return kj::HashMap, kj::Own>::Entry { kj::mv(ops), kj::mv(pipelineClient) }; } else { return kj::HashMap, kj::Own>::Entry { kj::mv(ops), newBrokenCap(kj::cp(state.get())) }; } })->addRef(); } private: kj::Own connectionState; kj::Maybe>> redirectLater; typedef kj::Own Waiting; typedef kj::Own Resolved; typedef kj::Exception Broken; kj::OneOf state; kj::HashMap, kj::Own> clientMap; // See QueuedPipeline::clientMap in capability.c++ for a discussion of why we must memoize // the results of getPipelinedCap(). RpcPipeline has a similar problem when a capability we // return is later subject to an embargo. It's important that the embargo is correctly applied // across all calls to the same capability. // Keep this last, because the continuation uses *this, so it should be destroyed first to // ensure the continuation is not still running. kj::Promise resolveSelfPromise; void resolve(kj::Own&& response) { KJ_ASSERT(state.is(), "Already resolved?"); state.init(kj::mv(response)); } void resolve(const kj::Exception&& exception) { KJ_ASSERT(state.is(), "Already resolved?"); state.init(kj::mv(exception)); } }; class RpcResponse: public ResponseHook { public: virtual AnyPointer::Reader getResults() = 0; virtual kj::Own addRef() = 0; }; class RpcResponseImpl final: public RpcResponse, public kj::Refcounted { public: RpcResponseImpl(RpcConnectionState& connectionState, kj::Own&& questionRef, kj::Own&& message, kj::Array>> capTableArray, AnyPointer::Reader results) : connectionState(kj::addRef(connectionState)), message(kj::mv(message)), capTable(kj::mv(capTableArray)), reader(capTable.imbue(results)), questionRef(kj::mv(questionRef)) {} AnyPointer::Reader getResults() override { return reader; } kj::Own addRef() override { return kj::addRef(*this); } private: kj::Own connectionState; kj::Own message; ReaderCapabilityTable capTable; AnyPointer::Reader reader; kj::Own questionRef; }; // ===================================================================================== // CallContextHook implementation class RpcServerResponse { public: virtual AnyPointer::Builder getResultsBuilder() = 0; }; class RpcServerResponseImpl final: public RpcServerResponse { public: RpcServerResponseImpl(RpcConnectionState& connectionState, kj::Own&& message, rpc::Payload::Builder payload) : connectionState(connectionState), message(kj::mv(message)), payload(payload) {} AnyPointer::Builder getResultsBuilder() override { return capTable.imbue(payload.getContent()); } inline bool hasCapabilities() { return capTable.getTable().size() > 0; } kj::Maybe> send() { // Send the response and return the export list. Returns nullptr if there were no caps. // (Could return a non-null empty array if there were caps but none of them were exports.) // Build the cap table. auto capTable = this->capTable.getTable(); kj::Vector fds; auto exports = connectionState.writeDescriptors(capTable, payload, fds); message->setFds(fds.releaseAsArray()); // Populate `resolutionsAtReturnTime`. for (auto& slot: capTable) { KJ_IF_MAYBE(cap, slot) { auto inner = connectionState.getInnermostClient(**cap); if (inner.get() != cap->get()) { resolutionsAtReturnTime.upsert(cap->get(), kj::mv(inner), [&](kj::Own& existing, kj::Own&& replacement) { KJ_ASSERT(existing.get() == replacement.get()); }); } } } message->send(); if (capTable.size() == 0) { return nullptr; } else { return kj::mv(exports); } } struct Resolution { kj::Own returnedCap; // The capabiilty that appeared in the response message in this slot. kj::Own unwrapped; // Exactly what `getInnermostClient(returnedCap)` produced at the time that the return // message was encoded. }; Resolution getResolutionAtReturnTime(kj::ArrayPtr ops) { auto returnedCap = getResultsBuilder().asReader().getPipelinedCap(ops); kj::Own unwrapped; KJ_IF_MAYBE(u, resolutionsAtReturnTime.find(returnedCap.get())) { unwrapped = u->get()->addRef(); } else { unwrapped = returnedCap->addRef(); } return { kj::mv(returnedCap), kj::mv(unwrapped) }; } private: RpcConnectionState& connectionState; kj::Own message; BuilderCapabilityTable capTable; rpc::Payload::Builder payload; kj::HashMap> resolutionsAtReturnTime; // For each capability in `capTable` as of the time when the call returned, this map stores // the result of calling `getInnermostClient()` on that capability. This is needed in order // to solve the Tribble 4-way race condition described in the documentation for `Disembargo` // in `rpc.capnp`. `PostReturnRpcPipeline`, below, uses this. // // As an optimization, if the innermost client is exactly the same object then nothing is // stored in the map. }; class LocallyRedirectedRpcResponse final : public RpcResponse, public RpcServerResponse, public kj::Refcounted{ public: LocallyRedirectedRpcResponse(kj::Maybe sizeHint) : message(sizeHint.map([](MessageSize size) { return size.wordCount; }) .orDefault(SUGGESTED_FIRST_SEGMENT_WORDS)) {} AnyPointer::Builder getResultsBuilder() override { return message.getRoot(); } AnyPointer::Reader getResults() override { return message.getRoot(); } kj::Own addRef() override { return kj::addRef(*this); } private: MallocMessageBuilder message; }; class PostReturnRpcPipeline final: public PipelineHook, public kj::Refcounted { // Once an incoming call has returned, we may need to replace the `PipelineHook` with one that // correctly handles the Tribble 4-way race condition. Namely, we must ensure that if the // response contained any capabilities pointing back out to the network, then any further // pipelined calls received targetting those capabilities (as well as any Disembargo messages) // will resolve to the same network capability forever, *even if* that network capability is // itself a promise which later resolves to somewhere else. public: PostReturnRpcPipeline(kj::Own inner, RpcServerResponseImpl& response, kj::Own context) : inner(kj::mv(inner)), response(response), context(kj::mv(context)) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { auto resolved = response.getResolutionAtReturnTime(ops); auto original = inner->getPipelinedCap(ops); return getResolutionAtReturnTime(kj::mv(original), kj::mv(resolved)); } kj::Own getPipelinedCap(kj::Array&& ops) override { auto resolved = response.getResolutionAtReturnTime(ops); auto original = inner->getPipelinedCap(kj::mv(ops)); return getResolutionAtReturnTime(kj::mv(original), kj::mv(resolved)); } private: kj::Own inner; RpcServerResponseImpl& response; kj::Own context; // owns `response` kj::Own getResolutionAtReturnTime( kj::Own original, RpcServerResponseImpl::Resolution resolution) { // Wait for `original` to resolve to `resolution.returnedCap`, then return // `resolution.unwrapped`. ClientHook* ptr = original.get(); for (;;) { if (ptr == resolution.returnedCap.get()) { return kj::mv(resolution.unwrapped); } else KJ_IF_MAYBE(r, ptr->getResolved()) { ptr = r; } else { break; } } KJ_IF_MAYBE(p, ptr->whenMoreResolved()) { return newLocalPromiseClient(p->then( [this, original = kj::mv(original), resolution = kj::mv(resolution)] (kj::Own r) mutable { return getResolutionAtReturnTime(kj::mv(r), kj::mv(resolution)); })); } else if (ptr->isError() || ptr->isNull()) { // This is already a broken capability, the error probably explains what went wrong. In // any case, message ordering is irrelevant here since all calls will throw anyway. return ptr->addRef(); } else { return newBrokenCap( "An RPC call's capnp::PipelineHook object resolved a pipelined capability to a " "different final object than what was returned in the actual response. This could " "be a bug in Cap'n Proto, or could be due to a use of context.setPipeline() that " "was inconsistent with the later results."); } } }; class RpcCallContext final: public CallContextHook, public kj::Refcounted { public: RpcCallContext(RpcConnectionState& connectionState, AnswerId answerId, kj::Own&& request, kj::Array>> capTableArray, const AnyPointer::Reader& params, bool redirectResults, uint64_t interfaceId, uint16_t methodId, ClientHook::CallHints hints) : connectionState(kj::addRef(connectionState)), answerId(answerId), hints(hints), interfaceId(interfaceId), methodId(methodId), requestSize(request->sizeInWords()), request(kj::mv(request)), paramsCapTable(kj::mv(capTableArray)), params(paramsCapTable.imbue(params)), returnMessage(nullptr), redirectResults(redirectResults) { connectionState.callWordsInFlight += requestSize; } ~RpcCallContext() noexcept(false) { if (isFirstResponder()) { // We haven't sent a return yet, so we must have been canceled. Send a cancellation return. unwindDetector.catchExceptionsIfUnwinding([&]() { // Don't send anything if the connection is broken, or if the onlyPromisePipeline hint // was used (in which case the caller doesn't care to receive a `Return`). bool shouldFreePipeline = true; if (connectionState->connection.is() && !hints.onlyPromisePipeline) { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint() + sizeInWords()); auto builder = message->getBody().initAs().initReturn(); builder.setAnswerId(answerId); builder.setReleaseParamCaps(false); if (redirectResults) { // The reason we haven't sent a return is because the results were sent somewhere // else. builder.setResultsSentElsewhere(); // The pipeline could still be valid and in-use in this case. shouldFreePipeline = false; } else { builder.setCanceled(); } message->send(); } cleanupAnswerTable(nullptr, shouldFreePipeline); }); } } kj::Own consumeRedirectedResponse() { KJ_ASSERT(redirectResults); if (response == nullptr) getResults(MessageSize{0, 0}); // force initialization of response // Note that the context needs to keep its own reference to the response so that it doesn't // get GC'd until the PipelineHook drops its reference to the context. return kj::downcast(*KJ_ASSERT_NONNULL(response)).addRef(); } void sendReturn() { KJ_ASSERT(!redirectResults); KJ_ASSERT(!hints.onlyPromisePipeline); // Avoid sending results if canceled so that we don't have to figure out whether or not // `releaseResultCaps` was set in the already-received `Finish`. if (!receivedFinish && isFirstResponder()) { KJ_ASSERT(connectionState->connection.is(), "Cancellation should have been requested on disconnect.") { return; } if (response == nullptr) getResults(MessageSize{0, 0}); // force initialization of response returnMessage.setAnswerId(answerId); returnMessage.setReleaseParamCaps(false); auto& responseImpl = kj::downcast(*KJ_ASSERT_NONNULL(response)); if (!responseImpl.hasCapabilities()) { returnMessage.setNoFinishNeeded(true); // Tell ourselves that a finsih was already received, so that `cleanupAnswerTable()` // removes the answer table entry. receivedFinish = true; // HACK: The answer table's `task` is the thing which is calling `sendReturn()`. We can't // cancel ourselves. However, we know calling `sendReturn()` is the last thing it does, // so we can safely detach() it. auto& answer = KJ_ASSERT_NONNULL(connectionState->answers.find(answerId)); auto& selfPromise = KJ_ASSERT_NONNULL(answer.task.tryGet()); selfPromise.detach([](kj::Exception&&) {}); } kj::Maybe> exports; KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { // Debug info in case send() fails due to overside message. KJ_CONTEXT("returning from RPC call", interfaceId, methodId); exports = responseImpl.send(); })) { responseSent = false; sendErrorReturn(kj::mv(*exception)); return; } if (responseImpl.hasCapabilities()) { auto& answer = KJ_ASSERT_NONNULL(connectionState->answers.find(answerId)); // Swap out the `pipeline` in the answer table for one that will return capabilities // consistent with whatever the result caps resolved to as of the time the return was sent. answer.pipeline = answer.pipeline.map([&](kj::Own& inner) { return kj::refcounted( kj::mv(inner), responseImpl, kj::addRef(*this)); }); } KJ_IF_MAYBE(e, exports) { // Caps were returned, so we can't free the pipeline yet. cleanupAnswerTable(kj::mv(*e), false); } else { // No caps in the results, therefore the pipeline is irrelevant. cleanupAnswerTable(nullptr, true); } } } void sendErrorReturn(kj::Exception&& exception) { KJ_ASSERT(!redirectResults); KJ_ASSERT(!hints.onlyPromisePipeline); if (isFirstResponder()) { if (connectionState->connection.is()) { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint() + exceptionSizeHint(exception)); auto builder = message->getBody().initAs().initReturn(); builder.setAnswerId(answerId); builder.setReleaseParamCaps(false); connectionState->fromException(exception, builder.initException()); // Note that even though the response contains no capabilities, we don't want to set // `noFinishNeeded` here because if any pipelined calls were made, we want them to // fail with the correct exception. (Perhaps if the request had `noPromisePipelining`, // then we could set `noFinishNeeded`, but optimizing the error case doesn't seem that // important.) message->send(); } // Do not allow releasing the pipeline because we want pipelined calls to propagate the // exception rather than fail with a "no such field" exception. cleanupAnswerTable(nullptr, false); } } void sendRedirectReturn() { KJ_ASSERT(redirectResults); KJ_ASSERT(!hints.onlyPromisePipeline); if (isFirstResponder()) { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint()); auto builder = message->getBody().initAs().initReturn(); builder.setAnswerId(answerId); builder.setReleaseParamCaps(false); builder.setResultsSentElsewhere(); // TODO(perf): Could `noFinishNeeded` be used here? The `Finish` messages are pretty // redundant after a redirect, but as this case is less common and more complicated I // don't want to fully think through the implications right now. message->send(); cleanupAnswerTable(nullptr, false); } } void finish() { // Called when a `Finish` message is received while this object still exists. receivedFinish = true; } // implements CallContextHook ------------------------------------ AnyPointer::Reader getParams() override { KJ_REQUIRE(request != nullptr, "Can't call getParams() after releaseParams()."); return params; } void releaseParams() override { request = nullptr; } AnyPointer::Builder getResults(kj::Maybe sizeHint) override { KJ_IF_MAYBE(r, response) { return r->get()->getResultsBuilder(); } else { kj::Own response; if (redirectResults || !connectionState->connection.is()) { response = kj::refcounted(sizeHint); } else { auto message = connectionState->connection.get()->newOutgoingMessage( firstSegmentSize(sizeHint, messageSizeHint() + sizeInWords())); returnMessage = message->getBody().initAs().initReturn(); response = kj::heap( *connectionState, kj::mv(message), returnMessage.getResults()); } auto results = response->getResultsBuilder(); this->response = kj::mv(response); return results; } } void setPipeline(kj::Own&& pipeline) override { KJ_IF_MAYBE(f, tailCallPipelineFulfiller) { f->get()->fulfill(AnyPointer::Pipeline(kj::mv(pipeline))); } } kj::Promise tailCall(kj::Own&& request) override { auto result = directTailCall(kj::mv(request)); KJ_IF_MAYBE(f, tailCallPipelineFulfiller) { f->get()->fulfill(AnyPointer::Pipeline(kj::mv(result.pipeline))); } return kj::mv(result.promise); } ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own&& request) override { KJ_REQUIRE(response == nullptr, "Can't call tailCall() after initializing the results struct."); if (request->getBrand() == connectionState.get() && !redirectResults && !hints.noPromisePipelining) { // The tail call is headed towards the peer that called us in the first place, so we can // optimize out the return trip. // // If the noPromisePipelining hint was sent, we skip this trick since the caller will // ignore the `Return` message anyway. KJ_IF_MAYBE(tailInfo, kj::downcast(*request).tailSend()) { if (isFirstResponder()) { if (connectionState->connection.is()) { auto message = connectionState->connection.get()->newOutgoingMessage( messageSizeHint()); auto builder = message->getBody().initAs().initReturn(); builder.setAnswerId(answerId); builder.setReleaseParamCaps(false); builder.setTakeFromOtherQuestion(tailInfo->questionId); message->send(); } // There are no caps in our return message, but of course the tail results could have // caps, so we must continue to honor pipeline calls (and just bounce them back). cleanupAnswerTable(nullptr, false); } return { kj::mv(tailInfo->promise), kj::mv(tailInfo->pipeline) }; } } // Just forwarding to another local call. if (hints.onlyPromisePipeline) { return { kj::NEVER_DONE, PipelineHook::from(request->sendForPipeline()) }; } auto promise = request->send(); // Wait for response. auto voidPromise = promise.then([this](Response&& tailResponse) { // Copy the response. // TODO(perf): It would be nice if we could somehow make the response get built in-place // but requires some refactoring. getResults(tailResponse.targetSize()).set(tailResponse); }); return { kj::mv(voidPromise), PipelineHook::from(kj::mv(promise)) }; } kj::Promise onTailCall() override { auto paf = kj::newPromiseAndFulfiller(); tailCallPipelineFulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } kj::Own addRef() override { return kj::addRef(*this); } private: kj::Own connectionState; AnswerId answerId; ClientHook::CallHints hints; uint64_t interfaceId; uint16_t methodId; // For debugging. // Request --------------------------------------------- size_t requestSize; // for flow limit purposes kj::Maybe> request; ReaderCapabilityTable paramsCapTable; AnyPointer::Reader params; // Response -------------------------------------------- kj::Maybe> response; rpc::Return::Builder returnMessage; bool redirectResults = false; bool responseSent = false; kj::Maybe>> tailCallPipelineFulfiller; // Cancellation state ---------------------------------- bool receivedFinish = false; // True if a `Finish` message has been recevied OR we sent a `Return` with `noFinishNedeed`. // In either case, it is our responsibility to clean up the answer table. kj::UnwindDetector unwindDetector; // ----------------------------------------------------- bool isFirstResponder() { if (responseSent) { return false; } else { responseSent = true; return true; } } void cleanupAnswerTable(kj::Array resultExports, bool shouldFreePipeline) { // We need to remove the `callContext` pointer -- which points back to us -- from the // answer table. Or we might even be responsible for removing the entire answer table // entry. if (receivedFinish) { // Already received `Finish` so it's our job to erase the table entry. We shouldn't have // sent results if canceled, so we shouldn't have an export list to deal with. KJ_ASSERT(resultExports.size() == 0); connectionState->answers.erase(answerId); } else { // We just have to null out callContext and set the exports. auto& answer = connectionState->answers[answerId]; answer.callContext = nullptr; answer.resultExports = kj::mv(resultExports); if (shouldFreePipeline) { // We can free the pipeline early, because we know all pipeline calls are invalid (e.g. // because there are no caps in the result to receive pipeline requests). KJ_ASSERT(resultExports.size() == 0); answer.pipeline = nullptr; } } // Also, this is the right time to stop counting the call against the flow limit. connectionState->callWordsInFlight -= requestSize; connectionState->maybeUnblockFlow(); } }; // ===================================================================================== // Message handling void maybeUnblockFlow() { if (callWordsInFlight < flowLimit) { KJ_IF_MAYBE(w, flowWaiter) { w->get()->fulfill(); flowWaiter = nullptr; } } } kj::Promise messageLoop() { if (!connection.is()) { return kj::READY_NOW; } if (callWordsInFlight > flowLimit) { auto paf = kj::newPromiseAndFulfiller(); flowWaiter = kj::mv(paf.fulfiller); return paf.promise.then([this]() { return messageLoop(); }); } return canceler.wrap(connection.get()->receiveIncomingMessage()).then( [this](kj::Maybe>&& message) { KJ_IF_MAYBE(m, message) { handleMessage(kj::mv(*m)); return true; } else { tasks.add(KJ_EXCEPTION(DISCONNECTED, "Peer disconnected.")); return false; } }, [this](kj::Exception&& exception) { receiveIncomingMessageError = true; kj::throwRecoverableException(kj::mv(exception)); return false; }).then([this](bool keepGoing) { // No exceptions; continue loop. // // (We do this in a separate continuation to handle the case where exceptions are // disabled.) // // TODO(perf): We add an evalLater() here so that anything we needed to do in reaction to // the previous message has a chance to complete before the next message is handled. In // particular, without this, I observed an ordering problem: I saw a case where a `Return` // message was followed by a `Resolve` message, but the `PromiseClient` associated with the // `Resolve` had its `resolve()` method invoked _before_ any `PromiseClient`s associated // with pipelined capabilities resolved by the `Return`. This could lead to an // incorrectly-ordered interaction between `PromiseClient`s when they resolve to each // other. This is probably really a bug in the way `Return`s are handled -- apparently, // resolution of `PromiseClient`s based on returned capabilities does not occur in a // depth-first way, when it should. If we could fix that then we can probably remove this // `evalLater()`. However, the `evalLater()` is not that bad and solves the problem... if (keepGoing) tasks.add(kj::evalLater([this]() { return messageLoop(); })); }); } void handleMessage(kj::Own message) { auto reader = message->getBody().getAs(); switch (reader.which()) { case rpc::Message::UNIMPLEMENTED: handleUnimplemented(reader.getUnimplemented()); break; case rpc::Message::ABORT: handleAbort(reader.getAbort()); break; case rpc::Message::BOOTSTRAP: handleBootstrap(kj::mv(message), reader.getBootstrap()); break; case rpc::Message::CALL: handleCall(kj::mv(message), reader.getCall()); break; case rpc::Message::RETURN: handleReturn(kj::mv(message), reader.getReturn()); break; case rpc::Message::FINISH: handleFinish(reader.getFinish()); break; case rpc::Message::RESOLVE: handleResolve(kj::mv(message), reader.getResolve()); break; case rpc::Message::RELEASE: handleRelease(reader.getRelease()); break; case rpc::Message::DISEMBARGO: handleDisembargo(reader.getDisembargo()); break; default: { if (connection.is()) { auto message = connection.get()->newOutgoingMessage( firstSegmentSize(reader.totalSize(), messageSizeHint())); message->getBody().initAs().setUnimplemented(reader); message->send(); } break; } } } void handleUnimplemented(const rpc::Message::Reader& message) { switch (message.which()) { case rpc::Message::RESOLVE: { auto resolve = message.getResolve(); switch (resolve.which()) { case rpc::Resolve::CAP: { auto cap = resolve.getCap(); switch (cap.which()) { case rpc::CapDescriptor::NONE: // Nothing to do (but this ought never to happen). break; case rpc::CapDescriptor::SENDER_HOSTED: releaseExport(cap.getSenderHosted(), 1); break; case rpc::CapDescriptor::SENDER_PROMISE: releaseExport(cap.getSenderPromise(), 1); break; case rpc::CapDescriptor::RECEIVER_ANSWER: case rpc::CapDescriptor::RECEIVER_HOSTED: // Nothing to do. break; case rpc::CapDescriptor::THIRD_PARTY_HOSTED: releaseExport(cap.getThirdPartyHosted().getVineId(), 1); break; } break; } case rpc::Resolve::EXCEPTION: // Nothing to do. break; } break; } default: KJ_FAIL_ASSERT("Peer did not implement required RPC message type.", (uint)message.which()); break; } } void handleAbort(const rpc::Exception::Reader& exception) { kj::throwRecoverableException(toException(exception)); } // --------------------------------------------------------------------------- // Level 0 class SingleCapPipeline: public PipelineHook, public kj::Refcounted { public: SingleCapPipeline(kj::Own&& cap) : cap(kj::mv(cap)) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { if (ops.size() == 0) { return cap->addRef(); } else { return newBrokenCap("Invalid pipeline transform."); } } private: kj::Own cap; }; void handleBootstrap(kj::Own&& message, const rpc::Bootstrap::Reader& bootstrap) { AnswerId answerId = bootstrap.getQuestionId(); if (!connection.is()) { // Disconnected; ignore. return; } VatNetworkBase::Connection& conn = *connection.get(); auto response = conn.newOutgoingMessage( messageSizeHint() + sizeInWords() + 32); rpc::Return::Builder ret = response->getBody().getAs().initReturn(); ret.setAnswerId(answerId); kj::Own capHook; kj::Array resultExports; KJ_DEFER(releaseExports(resultExports)); // in case something goes wrong // Call the restorer and initialize the answer. KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { Capability::Client cap = nullptr; if (bootstrap.hasDeprecatedObjectId()) { KJ_IF_MAYBE(r, restorer) { cap = r->baseRestore(bootstrap.getDeprecatedObjectId()); } else { KJ_FAIL_REQUIRE("This vat only supports a bootstrap interface, not the old " "Cap'n-Proto-0.4-style named exports.") { return; } } } else { cap = bootstrapFactory.baseCreateFor(conn.baseGetPeerVatId()); } BuilderCapabilityTable capTable; auto payload = ret.initResults(); capTable.imbue(payload.getContent()).setAs(kj::mv(cap)); auto capTableArray = capTable.getTable(); KJ_DASSERT(capTableArray.size() == 1); kj::Vector fds; resultExports = writeDescriptors(capTableArray, payload, fds); response->setFds(fds.releaseAsArray()); // If we're returning a capability that turns out to be an PromiseClient pointing back on // this same network, it's important we remove the `PromiseClient` layer and use the inner // capability instead. This achieves the same effect that `PostReturnRpcPipeline` does for // regular call returns. // // This single line of code represents two hours of my life. capHook = getInnermostClient(*KJ_ASSERT_NONNULL(capTableArray[0])); })) { fromException(*exception, ret.initException()); capHook = newBrokenCap(kj::mv(*exception)); } message = nullptr; // Add the answer to the answer table for pipelining and send the response. auto& answer = answers[answerId]; KJ_REQUIRE(!answer.active, "questionId is already in use", answerId) { return; } answer.resultExports = kj::mv(resultExports); answer.active = true; answer.pipeline = kj::Own(kj::refcounted(kj::mv(capHook))); response->send(); } void handleCall(kj::Own&& message, const rpc::Call::Reader& call) { kj::Own capability; KJ_IF_MAYBE(t, getMessageTarget(call.getTarget())) { capability = kj::mv(*t); } else { // Exception already reported. return; } bool redirectResults; switch (call.getSendResultsTo().which()) { case rpc::Call::SendResultsTo::CALLER: redirectResults = false; break; case rpc::Call::SendResultsTo::YOURSELF: redirectResults = true; break; default: KJ_FAIL_REQUIRE("Unsupported `Call.sendResultsTo`.") { return; } } auto payload = call.getParams(); auto capTableArray = receiveCaps(payload.getCapTable(), message->getAttachedFds()); AnswerId answerId = call.getQuestionId(); auto hints = callHintsFromReader(call); // Don't honor onlyPromisePipeline if results are redirected, because this situation isn't // useful in practice and would be complicated to handle "correctly". if (redirectResults) hints.onlyPromisePipeline = false; auto context = kj::refcounted( *this, answerId, kj::mv(message), kj::mv(capTableArray), payload.getContent(), redirectResults, call.getInterfaceId(), call.getMethodId(), hints); // No more using `call` after this point, as it now belongs to the context. { auto& answer = answers[answerId]; KJ_REQUIRE(!answer.active, "questionId is already in use") { return; } answer.active = true; answer.callContext = *context; } auto promiseAndPipeline = startCall( call.getInterfaceId(), call.getMethodId(), kj::mv(capability), context->addRef(), hints); // Things may have changed -- in particular if startCall() immediately called // context->directTailCall(). { auto& answer = answers[answerId]; answer.pipeline = kj::mv(promiseAndPipeline.pipeline); if (redirectResults) { answer.task = promiseAndPipeline.promise.then( [context=kj::mv(context)]() mutable { return context->consumeRedirectedResponse(); }); } else if (hints.onlyPromisePipeline) { // The promise is probably fake anyway, so don't bother adding a .then(). We do, however, // have to attach `context` to this, since we destroy `task` upon receiving a `Finish` // message, and we want `RpcCallContext` to be destroyed no earlier than that. answer.task = promiseAndPipeline.promise.attach(kj::mv(context)); } else { // Hack: Both the success and error continuations need to use the context. We could // refcount, but both will be destroyed at the same time anyway. RpcCallContext& contextRef = *context; answer.task = promiseAndPipeline.promise.then( [context = kj::mv(context)]() mutable { context->sendReturn(); }, [&contextRef](kj::Exception&& exception) { contextRef.sendErrorReturn(kj::mv(exception)); }).eagerlyEvaluate([&](kj::Exception&& exception) { // Handle exceptions that occur in sendReturn()/sendErrorReturn(). taskFailed(kj::mv(exception)); }); } } } ClientHook::VoidPromiseAndPipeline startCall( uint64_t interfaceId, uint64_t methodId, kj::Own&& capability, kj::Own&& context, ClientHook::CallHints hints) { return capability->call(interfaceId, methodId, kj::mv(context), hints); } kj::Maybe> getMessageTarget(const rpc::MessageTarget::Reader& target) { switch (target.which()) { case rpc::MessageTarget::IMPORTED_CAP: { KJ_IF_MAYBE(exp, exports.find(target.getImportedCap())) { return exp->clientHook->addRef(); } else { KJ_FAIL_REQUIRE("Message target is not a current export ID.") { return nullptr; } } break; } case rpc::MessageTarget::PROMISED_ANSWER: { auto promisedAnswer = target.getPromisedAnswer(); kj::Own pipeline; KJ_IF_MAYBE(answer, answers.find(promisedAnswer.getQuestionId())) { if (answer->active) { KJ_IF_MAYBE(p, answer->pipeline) { pipeline = p->get()->addRef(); } } } if (pipeline.get() == nullptr) { pipeline = newBrokenPipeline(KJ_EXCEPTION(FAILED, "Pipeline call on a request that returned no capabilities or was already closed.")); } KJ_IF_MAYBE(ops, toPipelineOps(promisedAnswer.getTransform())) { return pipeline->getPipelinedCap(*ops); } else { // Exception already thrown. return nullptr; } } default: KJ_FAIL_REQUIRE("Unknown message target type.", target) { return nullptr; } } KJ_UNREACHABLE; } void handleReturn(kj::Own&& message, const rpc::Return::Reader& ret) { // Transitive destructors can end up manipulating the question table and invalidating our // pointer into it, so make sure these destructors run later. kj::Array exportsToRelease; KJ_DEFER(releaseExports(exportsToRelease)); kj::Maybe promiseToRelease; QuestionId questionId = ret.getAnswerId(); if (questions.isHigh(questionId)) { // We sent hints with this question saying we didn't want a `Return` but we got one anyway. // We cannot even look up the question on the question table because it's (remotely) possible // that we already removed it and re-allocated the ID to something else. So, we should ignore // the `Return`. But we might want to make note to stop using these hints, to protect against // the (again, remote) possibility of our ID space wrapping around and leading to confusion. if (ret.getReleaseParamCaps() && sentCapabilitiesInPipelineOnlyCall) { // Oh no, it appears the peer wants us to release any capabilities in the params, something // which only a level 0 peer would request (no version of the C++ RPC system has ever done // this). And it appears we did send capabilities in at least one pipeline-only call // previously. But we have no record of which capabilities were sent in *this* call, so // we cannot release them. Log an error about the leak. // // This scenario is unlikely to happen in practice, because sendForPipeline() is not useful // when talking to a peer that doesn't support capability-passing -- they couldn't possibly // return a capability to pipeline on! So, I'm not going to spend time to find a solution // for this corner case. We will log an error, though, just in case someone hits this // somehow. KJ_LOG(ERROR, "sendForPipeline() was used when sending an RPC to a peer, the parameters of that " "RPC included capabilities, but the peer seems to implement Cap'n Proto at level 0, " "meaning it does not support capability passing (or, at least, it sent a `Return` " "with `releaseParamCaps = true`). The capabilities that were sent may have been " "leaked (they won't be dropped until the connection closes)."); sentCapabilitiesInPipelineOnlyCall = false; // don't log again } gotReturnForHighQuestionId = true; return; } KJ_IF_MAYBE(question, questions.find(questionId)) { KJ_REQUIRE(question->isAwaitingReturn, "Duplicate Return.") { return; } question->isAwaitingReturn = false; if (ret.getReleaseParamCaps()) { exportsToRelease = kj::mv(question->paramExports); } else { question->paramExports = nullptr; } if (ret.getNoFinishNeeded()) { question->skipFinish = true; } KJ_IF_MAYBE(questionRef, question->selfRef) { switch (ret.which()) { case rpc::Return::RESULTS: { KJ_REQUIRE(!question->isTailCall, "Tail call `Return` must set `resultsSentElsewhere`, not `results`.") { return; } auto payload = ret.getResults(); auto capTableArray = receiveCaps(payload.getCapTable(), message->getAttachedFds()); questionRef->fulfill(kj::refcounted( *this, kj::addRef(*questionRef), kj::mv(message), kj::mv(capTableArray), payload.getContent())); break; } case rpc::Return::EXCEPTION: KJ_REQUIRE(!question->isTailCall, "Tail call `Return` must set `resultsSentElsewhere`, not `exception`.") { return; } questionRef->reject(toException(ret.getException())); break; case rpc::Return::CANCELED: KJ_FAIL_REQUIRE("Return message falsely claims call was canceled.") { return; } break; case rpc::Return::RESULTS_SENT_ELSEWHERE: KJ_REQUIRE(question->isTailCall, "`Return` had `resultsSentElsewhere` but this was not a tail call.") { return; } // Tail calls are fulfilled with a null pointer. questionRef->fulfill(kj::Own()); break; case rpc::Return::TAKE_FROM_OTHER_QUESTION: KJ_IF_MAYBE(answer, answers.find(ret.getTakeFromOtherQuestion())) { KJ_IF_MAYBE(response, answer->task.tryGet()) { questionRef->fulfill(kj::mv(*response)); answer->task = Answer::Finished(); KJ_IF_MAYBE(context, answer->callContext) { // Send the `Return` message for the call of which we're taking ownership, so // that the peer knows it can now tear down the call state. context->sendRedirectReturn(); } } else { KJ_FAIL_REQUIRE("`Return.takeFromOtherQuestion` referenced a call that did not " "use `sendResultsTo.yourself`.") { return; } } } else { KJ_FAIL_REQUIRE("`Return.takeFromOtherQuestion` had invalid answer ID.") { return; } } break; default: KJ_FAIL_REQUIRE("Unknown 'Return' type.") { return; } } } else { // This is a response to a question that we canceled earlier. if (ret.isTakeFromOtherQuestion()) { // This turned out to be a tail call back to us! We now take ownership of the tail call. // Since the caller canceled, we need to cancel out the tail call, if it still exists. KJ_IF_MAYBE(answer, answers.find(ret.getTakeFromOtherQuestion())) { // Indeed, it does still exist. // Throw away the result promise. promiseToRelease = kj::mv(answer->task); KJ_IF_MAYBE(context, answer->callContext) { // Send the `Return` message for the call of which we're taking ownership, so // that the peer knows it can now tear down the call state. context->sendRedirectReturn(); } } } // Looks like this question was canceled earlier, so `Finish` was already sent, with // `releaseResultCaps` set true so that we don't have to release them here. We can go // ahead and delete it from the table. questions.erase(ret.getAnswerId(), *question); } } else { KJ_FAIL_REQUIRE("Invalid question ID in Return message.") { return; } } } void handleFinish(const rpc::Finish::Reader& finish) { // Delay release of these things until return so that transitive destructors don't accidentally // modify the answer table and invalidate our pointer into it. kj::Array exportsToRelease; KJ_DEFER(releaseExports(exportsToRelease)); Answer answerToRelease; kj::Maybe> pipelineToRelease; kj::Maybe promiseToRelease; KJ_IF_MAYBE(answer, answers.find(finish.getQuestionId())) { if (!answer->active) { // Treat the same as if the answer wasn't in the table; see comment below. return; } if (finish.getReleaseResultCaps()) { exportsToRelease = kj::mv(answer->resultExports); } else { answer->resultExports = nullptr; } pipelineToRelease = kj::mv(answer->pipeline); KJ_IF_MAYBE(context, answer->callContext) { // Destroying answer->task will probably destroy the call context, but we can't prove that // since it's refcounted. Instead, inform the call context that it is now its job to // clean up the answer table. Then, cancel the task. promiseToRelease = kj::mv(answer->task); answer->task = Answer::Finished(); context->finish(); } else { // The call context is already gone so we can tear down the Answer here. answerToRelease = answers.erase(finish.getQuestionId()); } } else { // The `Finish` message targets a qusetion ID that isn't present in our answer table. // Probably, we send a `Return` with `noFinishNeeded = true`, but the other side didn't // recognize this hint and sent a `Finish` anyway, or the `Finish` was already in-flight at // the time we sent the `Return`. We can silently ignore this. // // It would be nice to detect invalid finishes somehow, but to do so we would have to // remember past answer IDs somewhere even when we said `noFinishNeeded`. Assuming the other // side respects the hint and doesn't send a `Finish`, we'd only be able to clean up these // records when the other end reuses the question ID, which might never happen. } if (finish.getRequireEarlyCancellationWorkaround()) { // Defer actual cancellation of the call until the end of the event loop queue. // // This is needed for compatibility with older versions of Cap'n Proto (0.10 and prior) in // which the default was to prohibit cancellation until it was explicitly allowed. In newer // versions (1.0 and later) cancellation is allowed until explicitly prohibited, that is, if // we haven't actually delivered the call yet, it can be canceled. This requires less // bookkeeping and so improved performance. // // However, old clients might be inadvertently relying on the old behavior. For example, if // someone using and old version called `.send()` on a message and then promptly dropped the // returned Promise, the message would often be delivered. This was not intended to work, but // did, and could be relied upon by accident. Moreover, the original implementation of // streaming included a bug where streaming calls *always* sent an immediate Finish. // // By deferring cancellation until after a turn of the event loop, we provide an opportunity // for any `Call` messages we've received to actually be delivered, so that they can opt out // of cancellation if desired. KJ_IF_MAYBE(task, promiseToRelease) { KJ_IF_MAYBE(running, task->tryGet()) { tasks.add(kj::evalLast([running = kj::mv(*running)]() { // Just drop `running` here to cancel the call. })); } } } } // --------------------------------------------------------------------------- // Level 1 void handleResolve(kj::Own&& message, const rpc::Resolve::Reader& resolve) { kj::Own replacement; kj::Maybe exception; // Extract the replacement capability. switch (resolve.which()) { case rpc::Resolve::CAP: KJ_IF_MAYBE(cap, receiveCap(resolve.getCap(), message->getAttachedFds())) { replacement = kj::mv(*cap); } else { KJ_FAIL_REQUIRE("'Resolve' contained 'CapDescriptor.none'.") { return; } } break; case rpc::Resolve::EXCEPTION: // We can't set `replacement` to a new broken cap here because this will confuse // PromiseClient::Resolve() into thinking that the remote promise resolved to a local // capability and therefore a Disembargo is needed. We must actually reject the promise. exception = toException(resolve.getException()); break; default: KJ_FAIL_REQUIRE("Unknown 'Resolve' type.") { return; } } // If the import is on the table, fulfill it. KJ_IF_MAYBE(import, imports.find(resolve.getPromiseId())) { KJ_IF_MAYBE(fulfiller, import->promiseFulfiller) { // OK, this is in fact an unfulfilled promise! KJ_IF_MAYBE(e, exception) { fulfiller->get()->reject(kj::mv(*e)); } else { fulfiller->get()->fulfill(kj::mv(replacement)); } } else if (import->importClient != nullptr) { // It appears this is a valid entry on the import table, but was not expected to be a // promise. KJ_FAIL_REQUIRE("Got 'Resolve' for a non-promise import.") { break; } } } } void handleRelease(const rpc::Release::Reader& release) { releaseExport(release.getId(), release.getReferenceCount()); } void releaseExport(ExportId id, uint refcount) { KJ_IF_MAYBE(exp, exports.find(id)) { KJ_REQUIRE(refcount <= exp->refcount, "Tried to drop export's refcount below zero.") { return; } exp->refcount -= refcount; if (exp->refcount == 0) { exportsByCap.erase(exp->clientHook); exports.erase(id, *exp); } } else { KJ_FAIL_REQUIRE("Tried to release invalid export ID.") { return; } } } void releaseExports(kj::ArrayPtr exports) { for (auto exportId: exports) { releaseExport(exportId, 1); } } void handleDisembargo(const rpc::Disembargo::Reader& disembargo) { auto context = disembargo.getContext(); switch (context.which()) { case rpc::Disembargo::Context::SENDER_LOOPBACK: { kj::Own target; KJ_IF_MAYBE(t, getMessageTarget(disembargo.getTarget())) { target = kj::mv(*t); } else { // Exception already reported. return; } EmbargoId embargoId = context.getSenderLoopback(); // It's possible that `target` is a promise capability that hasn't resolved yet, in which // case we must wait for the resolution. In particular this can happen in the case where // we have Alice -> Bob -> Carol, Alice makes a call that proxies from Bob to Carol, and // Carol returns a capability from this call that points all the way back though Bob to // Alice. When this return capability passes through Bob, Bob will resolve the previous // promise-pipeline capability to it. However, Bob has to send a Disembargo to Carol before // completing this resolution. In the meantime, though, Bob returns the final repsonse to // Alice. Alice then *also* sends a Disembargo to Bob. The Alice -> Bob Disembargo might // arrive at Bob before the Bob -> Carol Disembargo has resolved, in which case the // Disembargo is delivered to a promise capability. auto promise = target->whenResolved() .then([]() { // We also need to insert an evalLast() here to make sure that any pending calls towards // this cap have had time to find their way through the event loop. return kj::evalLast([]() {}); }); tasks.add(promise.then([this, embargoId, target = kj::mv(target)]() mutable { for (;;) { KJ_IF_MAYBE(r, target->getResolved()) { target = r->addRef(); } else { break; } } KJ_REQUIRE(target->getBrand() == this, "'Disembargo' of type 'senderLoopback' sent to an object that does not point " "back to the sender.") { return; } if (!connection.is()) { return; } RpcClient& downcasted = kj::downcast(*target); auto message = connection.get()->newOutgoingMessage( messageSizeHint() + MESSAGE_TARGET_SIZE_HINT); auto builder = message->getBody().initAs().initDisembargo(); { auto redirect = downcasted.writeTarget(builder.initTarget()); // Disembargoes should only be sent to capabilities that were previously the subject of // a `Resolve` message. But `writeTarget` only ever returns non-null when called on // a PromiseClient. The code which sends `Resolve` and `Return` should have replaced // any promise with a direct node in order to solve the Tribble 4-way race condition. // See the documentation of Disembargo in rpc.capnp for more. KJ_REQUIRE(redirect == nullptr, "'Disembargo' of type 'senderLoopback' sent to an object that does not " "appear to have been the subject of a previous 'Resolve' message.") { return; } } builder.getContext().setReceiverLoopback(embargoId); message->send(); })); break; } case rpc::Disembargo::Context::RECEIVER_LOOPBACK: { KJ_IF_MAYBE(embargo, embargoes.find(context.getReceiverLoopback())) { KJ_ASSERT_NONNULL(embargo->fulfiller)->fulfill(); embargoes.erase(context.getReceiverLoopback(), *embargo); } else { KJ_FAIL_REQUIRE("Invalid embargo ID in 'Disembargo.context.receiverLoopback'.") { return; } } break; } default: KJ_FAIL_REQUIRE("Unimplemented Disembargo type.", disembargo) { return; } } } // --------------------------------------------------------------------------- // Level 2 }; } // namespace class RpcSystemBase::Impl final: private BootstrapFactoryBase, private kj::TaskSet::ErrorHandler { public: Impl(VatNetworkBase& network, kj::Maybe bootstrapInterface) : network(network), bootstrapInterface(kj::mv(bootstrapInterface)), bootstrapFactory(*this), tasks(*this) { acceptLoopPromise = acceptLoop().eagerlyEvaluate([](kj::Exception&& e) { KJ_LOG(ERROR, e); }); } Impl(VatNetworkBase& network, BootstrapFactoryBase& bootstrapFactory) : network(network), bootstrapFactory(bootstrapFactory), tasks(*this) { acceptLoopPromise = acceptLoop().eagerlyEvaluate([](kj::Exception&& e) { KJ_LOG(ERROR, e); }); } Impl(VatNetworkBase& network, SturdyRefRestorerBase& restorer) : network(network), bootstrapFactory(*this), restorer(restorer), tasks(*this) { acceptLoopPromise = acceptLoop().eagerlyEvaluate([](kj::Exception&& e) { KJ_LOG(ERROR, e); }); } ~Impl() noexcept(false) { unwindDetector.catchExceptionsIfUnwinding([&]() { // std::unordered_map doesn't like it when elements' destructors throw, so carefully // disassemble it. if (!connections.empty()) { kj::Vector> deleteMe(connections.size()); kj::Exception shutdownException = KJ_EXCEPTION(DISCONNECTED, "RpcSystem was destroyed."); for (auto& entry: connections) { entry.second->disconnect(kj::cp(shutdownException)); deleteMe.add(kj::mv(entry.second)); } } }); } Capability::Client bootstrap(AnyStruct::Reader vatId) { // For now we delegate to restore() since it's equivalent, but eventually we'll remove restore() // and implement bootstrap() directly. return restore(vatId, AnyPointer::Reader()); } Capability::Client restore(AnyStruct::Reader vatId, AnyPointer::Reader objectId) { KJ_IF_MAYBE(connection, network.baseConnect(vatId)) { auto& state = getConnectionState(kj::mv(*connection)); return Capability::Client(state.restore(objectId)); } else if (objectId.isNull()) { // Turns out `vatId` refers to ourselves, so we can also pass it as the client ID for // baseCreateFor(). return bootstrapFactory.baseCreateFor(vatId); } else KJ_IF_MAYBE(r, restorer) { return r->baseRestore(objectId); } else { return Capability::Client(newBrokenCap( "This vat only supports a bootstrap interface, not the old Cap'n-Proto-0.4-style " "named exports.")); } } void setFlowLimit(size_t words) { flowLimit = words; for (auto& conn: connections) { conn.second->setFlowLimit(words); } } void setTraceEncoder(kj::Function func) { traceEncoder = kj::mv(func); } kj::Promise run() { return kj::mv(acceptLoopPromise); } private: VatNetworkBase& network; kj::Maybe bootstrapInterface; BootstrapFactoryBase& bootstrapFactory; kj::Maybe restorer; size_t flowLimit = kj::maxValue; kj::Maybe> traceEncoder; kj::Promise acceptLoopPromise = nullptr; kj::TaskSet tasks; typedef std::unordered_map> ConnectionMap; ConnectionMap connections; kj::UnwindDetector unwindDetector; RpcConnectionState& getConnectionState(kj::Own&& connection) { auto iter = connections.find(connection); if (iter == connections.end()) { VatNetworkBase::Connection* connectionPtr = connection; auto onDisconnect = kj::newPromiseAndFulfiller(); tasks.add(onDisconnect.promise .then([this,connectionPtr](RpcConnectionState::DisconnectInfo info) { connections.erase(connectionPtr); tasks.add(kj::mv(info.shutdownPromise)); })); auto newState = kj::refcounted( bootstrapFactory, restorer, kj::mv(connection), kj::mv(onDisconnect.fulfiller), flowLimit, traceEncoder); RpcConnectionState& result = *newState; connections.insert(std::make_pair(connectionPtr, kj::mv(newState))); return result; } else { return *iter->second; } } kj::Promise acceptLoop() { return network.baseAccept().then( [this](kj::Own&& connection) { getConnectionState(kj::mv(connection)); return acceptLoop(); }); } Capability::Client baseCreateFor(AnyStruct::Reader clientId) override { // Implements BootstrapFactory::baseCreateFor() in terms of `bootstrapInterface` or `restorer`, // for use when we were given one of those instead of an actual `bootstrapFactory`. KJ_IF_MAYBE(cap, bootstrapInterface) { return *cap; } else KJ_IF_MAYBE(r, restorer) { return r->baseRestore(AnyPointer::Reader()); } else { return KJ_EXCEPTION(FAILED, "This vat does not expose any public/bootstrap interfaces."); } } void taskFailed(kj::Exception&& exception) override { KJ_LOG(ERROR, exception); } }; RpcSystemBase::RpcSystemBase(VatNetworkBase& network, kj::Maybe bootstrapInterface) : impl(kj::heap(network, kj::mv(bootstrapInterface))) {} RpcSystemBase::RpcSystemBase(VatNetworkBase& network, BootstrapFactoryBase& bootstrapFactory) : impl(kj::heap(network, bootstrapFactory)) {} RpcSystemBase::RpcSystemBase(VatNetworkBase& network, SturdyRefRestorerBase& restorer) : impl(kj::heap(network, restorer)) {} RpcSystemBase::RpcSystemBase(RpcSystemBase&& other) noexcept = default; RpcSystemBase::~RpcSystemBase() noexcept(false) {} Capability::Client RpcSystemBase::baseBootstrap(AnyStruct::Reader vatId) { return impl->bootstrap(vatId); } Capability::Client RpcSystemBase::baseRestore( AnyStruct::Reader hostId, AnyPointer::Reader objectId) { return impl->restore(hostId, objectId); } void RpcSystemBase::baseSetFlowLimit(size_t words) { return impl->setFlowLimit(words); } void RpcSystemBase::setTraceEncoder(kj::Function func) { impl->setTraceEncoder(kj::mv(func)); } kj::Promise RpcSystemBase::run() { return impl->run(); } } // namespace _ (private) // ======================================================================================= namespace { class WindowFlowController final: public RpcFlowController, private kj::TaskSet::ErrorHandler { public: WindowFlowController(RpcFlowController::WindowGetter& windowGetter) : windowGetter(windowGetter), tasks(*this) { state.init(); } kj::Promise send(kj::Own message, kj::Promise ack) override { auto size = message->sizeInWords() * sizeof(capnp::word); maxMessageSize = kj::max(size, maxMessageSize); // We are REQUIRED to send the message NOW to maintain correct ordering. message->send(); inFlight += size; tasks.add(ack.then([this, size]() { inFlight -= size; KJ_SWITCH_ONEOF(state) { KJ_CASE_ONEOF(blockedSends, Running) { if (isReady()) { // Release all fulfillers. for (auto& fulfiller: blockedSends) { fulfiller->fulfill(); } blockedSends.clear(); } KJ_IF_MAYBE(f, emptyFulfiller) { if (inFlight == 0) { f->get()->fulfill(tasks.onEmpty()); } } } KJ_CASE_ONEOF(exception, kj::Exception) { // A previous call failed, but this one -- which was already in-flight at the time -- // ended up succeeding. That may indicate that the server side is not properly // handling streaming error propagation. Nothing much we can do about it here though. } } })); KJ_SWITCH_ONEOF(state) { KJ_CASE_ONEOF(blockedSends, Running) { if (isReady()) { return kj::READY_NOW; } else { auto paf = kj::newPromiseAndFulfiller(); blockedSends.add(kj::mv(paf.fulfiller)); return kj::mv(paf.promise); } } KJ_CASE_ONEOF(exception, kj::Exception) { return kj::cp(exception); } } KJ_UNREACHABLE; } kj::Promise waitAllAcked() override { KJ_IF_MAYBE(q, state.tryGet()) { if (!q->empty()) { auto paf = kj::newPromiseAndFulfiller>(); emptyFulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } } return tasks.onEmpty(); } private: RpcFlowController::WindowGetter& windowGetter; size_t inFlight = 0; size_t maxMessageSize = 0; typedef kj::Vector>> Running; kj::OneOf state; kj::Maybe>>> emptyFulfiller; kj::TaskSet tasks; void taskFailed(kj::Exception&& exception) override { KJ_SWITCH_ONEOF(state) { KJ_CASE_ONEOF(blockedSends, Running) { // Fail out all pending sends. for (auto& fulfiller: blockedSends) { fulfiller->reject(kj::cp(exception)); } // Fail out all future sends. state = kj::mv(exception); } KJ_CASE_ONEOF(exception, kj::Exception) { // ignore redundant exception } } } bool isReady() { // We extend the window by maxMessageSize to avoid a pathological situation when a message // is larger than the window size. Otherwise, after sending that message, we would end up // not sending any others until the ack was received, wasting a round trip's worth of // bandwidth. return inFlight <= maxMessageSize // avoid getWindow() call if unnecessary || inFlight < windowGetter.getWindow() + maxMessageSize; } }; class FixedWindowFlowController final : public RpcFlowController, public RpcFlowController::WindowGetter { public: FixedWindowFlowController(size_t windowSize): windowSize(windowSize), inner(*this) {} kj::Promise send(kj::Own message, kj::Promise ack) override { return inner.send(kj::mv(message), kj::mv(ack)); } kj::Promise waitAllAcked() override { return inner.waitAllAcked(); } size_t getWindow() override { return windowSize; } private: size_t windowSize; WindowFlowController inner; }; } // namespace kj::Own RpcFlowController::newFixedWindowController(size_t windowSize) { return kj::heap(windowSize); } kj::Own RpcFlowController::newVariableWindowController(WindowGetter& getter) { return kj::heap(getter); } bool IncomingRpcMessage::isShortLivedRpcMessage(AnyPointer::Reader body) { switch (body.getAs().which()) { case rpc::Message::CALL: case rpc::Message::RETURN: return false; default: return true; } } kj::Function IncomingRpcMessage::getShortLivedCallback() { return [](MessageReader& reader) { return IncomingRpcMessage::isShortLivedRpcMessage(reader.getRoot()); }; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/c++.capnp0000644000175000017500000000523014527152321020227 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xbdf87d7bb8304e81; $namespace("capnp::annotations"); annotation namespace(file): Text; annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; annotation allowCancellation(interface, method, file) :Void; # Indicates that the server-side implementation of a method is allowed to be canceled when the # client requests cancellation. Without this annotation, once a method call has been delivered to # the server-side application code, any requests by the client to cancel it will be ignored, and # the method will run to completion anyway. This applies even for local in-process calls. # # This behavior applies specifically to implementations that inherit from the C++ `Foo::Server` # interface. The annotation won't affect DynamicCapability::Server implementations; they must set # the cancellation mode at runtime. # # When applied to an interface rather than an individual method, the annotation applies to all # methods in the interface. When applied to a file, it applies to all methods defined in the file. # # It's generally recommended that this annotation be applied to all methods. However, when doing # so, it is important that the server implementation use cancellation-safe code. See: # # https://github.com/capnproto/capnproto/blob/master/kjdoc/tour.md#cancellation # # If your code is not cancellation-safe, then allowing cancellation might give a malicious client # an easy way to induce use-after-free or other bugs in your server, by requesting cancellation # when not expected. capnproto-c++-1.1.0/src/capnp/list.h0000644000175000017500000005127414712011043017760 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "layout.h" #include "orphan.h" #include CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private template class TemporaryPointer { // This class is a little hack which lets us define operator->() in cases where it needs to // return a pointer to a temporary value. We instead construct a TemporaryPointer and return that // (by value). The compiler then invokes operator->() on the TemporaryPointer, which itself is // able to return a real pointer to its member. public: TemporaryPointer(T&& value): value(kj::mv(value)) {} TemporaryPointer(const T& value): value(value) {} inline T* operator->() { return &value; } private: T value; }; // By default this isn't compatible with STL algorithms. To add STL support either define // KJ_STD_COMPAT at the top of your compilation unit or include capnp/compat/std-iterator.h. template class IndexingIterator { public: IndexingIterator() = default; inline Element operator*() const { return (*container)[index]; } inline TemporaryPointer operator->() const { return TemporaryPointer((*container)[index]); } inline Element operator[]( int off) const { return (*container)[index]; } inline Element operator[](uint off) const { return (*container)[index]; } inline IndexingIterator& operator++() { ++index; return *this; } inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; } inline IndexingIterator& operator--() { --index; return *this; } inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; } inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); } inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); } inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); } inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); } inline int operator-(const IndexingIterator& other) const { return index - other.index; } inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; } inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; } inline IndexingIterator& operator+=( int amount) { index += amount; return *this; } inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; } // STL says comparing iterators of different containers is not allowed, so we only compare // indices here. inline bool operator==(const IndexingIterator& other) const { return index == other.index; } inline bool operator!=(const IndexingIterator& other) const { return index != other.index; } inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; } inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; } inline bool operator< (const IndexingIterator& other) const { return index < other.index; } inline bool operator> (const IndexingIterator& other) const { return index > other.index; } private: Container* container; uint index; friend Container; inline IndexingIterator(Container* container, uint index) : container(container), index(index) {} }; } // namespace _ (private) template struct List { // List of primitives. List() = delete; class Reader { public: typedef List Reads; inline Reader(): reader(_::elementSizeForType()) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline T operator[](uint index) const { KJ_IREQUIRE(index < size()); return reader.template getDataElement(bounded(index) * ELEMENTS); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List Builds; inline Builder(): builder(_::elementSizeForType()) {} inline Builder(decltype(nullptr)): Builder() {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline T operator[](uint index) { KJ_IREQUIRE(index < size()); return builder.template getDataElement(bounded(index) * ELEMENTS); } inline void set(uint index, T value) { // Alas, it is not possible to make operator[] return a reference to which you can assign, // since the encoded representation does not necessarily match the compiler's representation // of the type. We can't even return a clever class that implements operator T() and // operator=() because it will lead to surprising behavior when using type inference (e.g. // calling a template function with inferred argument types, or using "auto" or "decltype"). builder.template setDataElement(bounded(index) * ELEMENTS, value); } typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; class Pipeline {}; private: inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { return builder.initList(_::elementSizeForType(), bounded(size) * ELEMENTS); } inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { return builder.getList(_::elementSizeForType(), defaultValue); } inline static _::ListReader getFromPointer( const _::PointerReader& reader, const word* defaultValue) { return reader.getList(_::elementSizeForType(), defaultValue); } template friend struct List; template friend struct _::PointerHelpers; }; template struct List: public List {}; template struct List { // List of structs. List() = delete; class Reader { public: typedef List Reads; inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline typename T::Reader operator[](uint index) const { KJ_IREQUIRE(index < size()); return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS)); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List Builds; inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {} inline Builder(decltype(nullptr)): Builder() {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline typename T::Builder operator[](uint index) { KJ_IREQUIRE(index < size()); return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS)); } inline void adoptWithCaveats(uint index, Orphan&& orphan) { // Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from // the fact that structs in a struct list are allocated inline rather than by pointer: // * This actually performs a shallow copy, effectively adopting each of the orphan's // children rather than adopting the orphan itself. The orphan ends up being discarded, // possibly wasting space in the message object. // * If the orphan is larger than the target struct -- say, because the orphan was built // using a newer version of the schema that has additional fields -- it will be truncated, // losing data. KJ_IREQUIRE(index < size()); // We pass a zero-valued StructSize to asStruct() because we do not want the struct to be // expanded under any circumstances. We're just going to throw it away anyway, and // transferContentFrom() already carefully compares the struct sizes before transferring. builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom( orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); } inline void setWithCaveats(uint index, const typename T::Reader& reader) { // Mostly behaves like you'd expect `set` to behave, but with a caveat originating from // the fact that structs in a struct list are allocated inline rather than by pointer: // If the source struct is larger than the target struct -- say, because the source was built // using a newer version of the schema that has additional fields -- it will be truncated, // losing data. // // Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to // do it without losing any data in case the source lists come from a newer version of the // protocol. (Plus, it's easier to use anyhow.) KJ_IREQUIRE(index < size()); builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader); } // There are no init(), set(), adopt(), or disown() methods for lists of structs because the // elements of the list are inlined and are initialized when the list is initialized. This // means that init() would be redundant, and set() would risk data loss if the input struct // were from a newer version of the protocol. typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; class Pipeline {}; private: inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { return builder.initStructList(bounded(size) * ELEMENTS, _::structSize()); } inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { return builder.getStructList(_::structSize(), defaultValue); } inline static _::ListReader getFromPointer( const _::PointerReader& reader, const word* defaultValue) { return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue); } template friend struct List; template friend struct _::PointerHelpers; }; template struct List, Kind::LIST> { // List of lists. List() = delete; class Reader { public: typedef List> Reads; inline Reader(): reader(ElementSize::POINTER) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline typename List::Reader operator[](uint index) const { KJ_IREQUIRE(index < size()); return typename List::Reader(_::PointerHelpers>::get( reader.getPointerElement(bounded(index) * ELEMENTS))); } typedef _::IndexingIterator::Reader> Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List> Builds; inline Builder(): builder(ElementSize::POINTER) {} inline Builder(decltype(nullptr)): Builder() {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline typename List::Builder operator[](uint index) { KJ_IREQUIRE(index < size()); return typename List::Builder(_::PointerHelpers>::get( builder.getPointerElement(bounded(index) * ELEMENTS))); } inline typename List::Builder init(uint index, uint size) { KJ_IREQUIRE(index < this->size()); return typename List::Builder(_::PointerHelpers>::init( builder.getPointerElement(bounded(index) * ELEMENTS), size)); } inline void set(uint index, typename List::Reader value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader); } void set(uint index, std::initializer_list> value) { KJ_IREQUIRE(index < size()); auto l = init(index, value.size()); uint i = 0; for (auto& element: value) { l.set(i++, element); } } inline void adopt(uint index, Orphan>&& value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); } inline Orphan> disown(uint index) { KJ_IREQUIRE(index < size()); return Orphan>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); } typedef _::IndexingIterator::Builder> Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; class Pipeline {}; private: inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); } inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { return builder.getList(ElementSize::POINTER, defaultValue); } inline static _::ListReader getFromPointer( const _::PointerReader& reader, const word* defaultValue) { return reader.getList(ElementSize::POINTER, defaultValue); } template friend struct List; template friend struct _::PointerHelpers; }; template struct List { List() = delete; class Reader { public: typedef List Reads; inline Reader(): reader(ElementSize::POINTER) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline typename T::Reader operator[](uint index) const { KJ_IREQUIRE(index < size()); return reader.getPointerElement(bounded(index) * ELEMENTS) .template getBlob(nullptr, ZERO * BYTES); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List Builds; inline Builder(): builder(ElementSize::POINTER) {} inline Builder(decltype(nullptr)): Builder() {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline typename T::Builder operator[](uint index) { KJ_IREQUIRE(index < size()); return builder.getPointerElement(bounded(index) * ELEMENTS) .template getBlob(nullptr, ZERO * BYTES); } inline void set(uint index, typename T::Reader value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob(value); } inline typename T::Builder init(uint index, uint size) { KJ_IREQUIRE(index < this->size()); return builder.getPointerElement(bounded(index) * ELEMENTS) .template initBlob(bounded(size) * BYTES); } inline void adopt(uint index, Orphan&& value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder)); } inline Orphan disown(uint index) { KJ_IREQUIRE(index < size()); return Orphan(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); } typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; class Pipeline {}; private: inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); } inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { return builder.getList(ElementSize::POINTER, defaultValue); } inline static _::ListReader getFromPointer( const _::PointerReader& reader, const word* defaultValue) { return reader.getList(ElementSize::POINTER, defaultValue); } template friend struct List; template friend struct _::PointerHelpers; }; } // namespace capnp #ifdef KJ_STD_COMPAT #include "compat/std-iterator.h" #endif // KJ_STD_COMPAT CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/CMakeLists.txt0000644000175000017500000002455214712011043021373 0ustar00kentonkenton00000000000000 # capnp ======================================================================== set(capnp_sources_lite c++.capnp.c++ blob.c++ arena.c++ layout.c++ list.c++ any.c++ message.c++ schema.capnp.c++ stream.capnp.c++ serialize.c++ serialize-packed.c++ ) set(capnp_sources_heavy schema.c++ schema-loader.c++ dynamic.c++ stringify.c++ ) if(NOT CAPNP_LITE) set(capnp_sources ${capnp_sources_lite} ${capnp_sources_heavy}) else() set(capnp_sources ${capnp_sources_lite}) endif() set(capnp_headers c++.capnp.h common.h blob.h endian.h layout.h orphan.h list.h any.h message.h capability.h membrane.h dynamic.h schema.h schema.capnp.h stream.capnp.h schema-lite.h schema-loader.h schema-parser.h pretty-print.h serialize.h serialize-async.h serialize-packed.h serialize-text.h pointer-helpers.h generated-header-support.h raw-schema.h ) set(capnp_compat_headers compat/std-iterator.h ) set(capnp_schemas c++.capnp schema.capnp stream.capnp ) add_library(capnp ${capnp_sources}) add_library(CapnProto::capnp ALIAS capnp) target_link_libraries(capnp PUBLIC kj) #make sure external consumers don't need to manually set the include dirs get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) target_include_directories(capnp INTERFACE $ $ ) # Ensure the library has a version set to match autotools build set_target_properties(capnp PROPERTIES VERSION ${VERSION}) install(TARGETS capnp ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${capnp_headers} ${capnp_schemas} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp") install(FILES ${capnp_compat_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp/compat") set(capnp-rpc_sources serialize-async.c++ capability.c++ membrane.c++ dynamic-capability.c++ rpc.c++ rpc.capnp.c++ rpc-twoparty.c++ rpc-twoparty.capnp.c++ persistent.capnp.c++ ez-rpc.c++ ) set(capnp-rpc_headers rpc-prelude.h rpc.h rpc-twoparty.h rpc.capnp.h rpc-twoparty.capnp.h persistent.capnp.h ez-rpc.h ) set(capnp-rpc_schemas rpc.capnp rpc-twoparty.capnp persistent.capnp ) if(NOT CAPNP_LITE) add_library(capnp-rpc ${capnp-rpc_sources}) add_library(CapnProto::capnp-rpc ALIAS capnp-rpc) target_link_libraries(capnp-rpc PUBLIC capnp kj-async kj) # Ensure the library has a version set to match autotools build set_target_properties(capnp-rpc PROPERTIES VERSION ${VERSION}) install(TARGETS capnp-rpc ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${capnp-rpc_headers} ${capnp-rpc_schemas} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp") endif() # capnp-json ======================================================================== set(capnp-json_sources compat/json.c++ compat/json.capnp.c++ ) set(capnp-json_headers compat/json.h compat/json.capnp.h ) set(capnp-json_schemas compat/json.capnp ) if(NOT CAPNP_LITE) add_library(capnp-json ${capnp-json_sources}) add_library(CapnProto::capnp-json ALIAS capnp-json) target_link_libraries(capnp-json PUBLIC capnp kj-async kj) # Ensure the library has a version set to match autotools build set_target_properties(capnp-json PROPERTIES VERSION ${VERSION}) install(TARGETS capnp-json ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${capnp-json_headers} ${capnp-json_schemas} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp/compat") endif() # capnp-websocket ======================================================================== set(capnp-websocket_sources compat/websocket-rpc.c++ ) set(capnp-websocket_headers compat/websocket-rpc.h ) if(NOT CAPNP_LITE) add_library(capnp-websocket ${capnp-websocket_sources}) add_library(CapnProto::capnp-websocket ALIAS capnp-websocket) target_link_libraries(capnp-websocket PUBLIC capnp capnp-rpc kj-http kj-async kj) # Ensure the library has a version set to match autotools build set_target_properties(capnp-websocket PROPERTIES VERSION ${VERSION}) install(TARGETS capnp-websocket ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${capnp-websocket_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp/compat") endif() # Tools/Compilers ============================================================== set(capnpc_sources compiler/type-id.c++ compiler/error-reporter.c++ compiler/lexer.capnp.c++ compiler/lexer.c++ compiler/grammar.capnp.c++ compiler/parser.c++ compiler/generics.c++ compiler/node-translator.c++ compiler/compiler.c++ schema-parser.c++ serialize-text.c++ ) if(NOT CAPNP_LITE) add_library(capnpc ${capnpc_sources}) target_link_libraries(capnpc PUBLIC capnp kj) # Ensure the library has a version set to match autotools build set_target_properties(capnpc PROPERTIES VERSION ${VERSION}) install(TARGETS capnpc ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${capnpc_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/capnp") endif() if(NOT CAPNP_LITE) add_executable(capnp_tool compiler/module-loader.c++ compiler/capnp.c++ ) target_link_libraries(capnp_tool capnpc capnp-json capnp kj) set_target_properties(capnp_tool PROPERTIES OUTPUT_NAME capnp) set_target_properties(capnp_tool PROPERTIES CAPNP_INCLUDE_DIRECTORY $,$> ) target_compile_definitions(capnp_tool PRIVATE "CAPNP_INCLUDE_DIR=\"${CMAKE_INSTALL_FULL_INCLUDEDIR}\"" "VERSION=\"${VERSION}\"" ) add_executable(capnpc_cpp compiler/capnpc-c++.c++ ) target_link_libraries(capnpc_cpp capnp kj) set_target_properties(capnpc_cpp PROPERTIES OUTPUT_NAME capnpc-c++) #Capnp tool needs capnpc_cpp location. But cmake deprecated LOCATION property. #So we use custom property to pass location set_target_properties(capnpc_cpp PROPERTIES CAPNPC_CXX_EXECUTABLE $ ) add_executable(capnpc_capnp compiler/capnpc-capnp.c++ ) target_link_libraries(capnpc_capnp capnp kj) set_target_properties(capnpc_capnp PROPERTIES OUTPUT_NAME capnpc-capnp) install(TARGETS capnp_tool capnpc_cpp capnpc_capnp ${INSTALL_TARGETS_DEFAULT_ARGS}) if(WIN32) # On Windows platforms symlinks are not guaranteed to support. Also different version of CMake handle create_symlink in a different way. # The most portable way in this case just copy the file. install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/capnp${CMAKE_EXECUTABLE_SUFFIX}\" \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/capnpc${CMAKE_EXECUTABLE_SUFFIX}\")") else() # Symlink capnpc -> capnp install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink capnp${CMAKE_EXECUTABLE_SUFFIX} \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/capnpc${CMAKE_EXECUTABLE_SUFFIX}\")") endif() endif() # NOT CAPNP_LITE # Tests ======================================================================== if(BUILD_TESTING) set(test_capnp_files test.capnp test-import.capnp test-import2.capnp compat/json-test.capnp ) set(CAPNPC_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/test_capnp") include_directories("${CAPNPC_OUTPUT_DIR}") file(MAKE_DIRECTORY "${CAPNPC_OUTPUT_DIR}") # Tell capnp_generate_cpp to set --src-prefix to our parent directory. This allows us to pass our # .capnp files relative to this directory, but have their canonical name end up as # capnp/test.capnp, capnp/test-import.capnp, etc. get_filename_component(CAPNPC_SRC_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY) capnp_generate_cpp(test_capnp_cpp_files test_capnp_h_files ${test_capnp_files}) # TODO(cleanup): capnp-tests and capnp-heavy-tests both depend on the test.capnp output files. In # a parallel Makefile-based build (maybe others?), they can race and cause the custom capnp # command in capnp_generate_cpp() to run twice. To get around this I'm using a custom target to # force CMake to generate race-free Makefiles. Remove this garbage when we move to a # target-based capnp_generate() command, as that will make CMake do the right thing by default. add_custom_target(test_capnp DEPENDS ${test_capnp_cpp_files} ${test_capnp_h_files}) if(CAPNP_LITE) set(test_libraries capnp kj-test kj) else() set(test_libraries capnp-json capnp-rpc capnp-websocket capnp capnpc kj-http kj-async kj-test kj) endif() add_executable(capnp-tests common-test.c++ blob-test.c++ endian-test.c++ endian-fallback-test.c++ layout-test.c++ any-test.c++ message-test.c++ encoding-test.c++ orphan-test.c++ serialize-test.c++ serialize-packed-test.c++ canonicalize-test.c++ fuzz-test.c++ test-util.c++ ${test_capnp_cpp_files} ${test_capnp_h_files} ) target_link_libraries(capnp-tests ${test_libraries}) add_dependencies(capnp-tests test_capnp) add_dependencies(check capnp-tests) add_test(NAME capnp-tests-run COMMAND capnp-tests) if(NOT CAPNP_LITE) add_executable(capnp-heavy-tests endian-reverse-test.c++ capability-test.c++ membrane-test.c++ schema-test.c++ schema-loader-test.c++ schema-parser-test.c++ dynamic-test.c++ stringify-test.c++ serialize-async-test.c++ serialize-text-test.c++ rpc-test.c++ rpc-twoparty-test.c++ ez-rpc-test.c++ compiler/lexer-test.c++ compiler/type-id-test.c++ test-util.c++ compat/json-test.c++ compat/websocket-rpc-test.c++ ${test_capnp_cpp_files} ${test_capnp_h_files} ) target_link_libraries(capnp-heavy-tests ${test_libraries}) if(NOT MSVC) set_target_properties(capnp-heavy-tests PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations" ) endif() add_dependencies(capnp-heavy-tests test_capnp) add_dependencies(check capnp-heavy-tests) add_test(NAME capnp-heavy-tests-run COMMAND capnp-heavy-tests) add_executable(capnp-evolution-tests compiler/evolution-test.c++) target_link_libraries(capnp-evolution-tests capnpc capnp kj) add_dependencies(check capnp-evolution-tests) add_test(NAME capnp-evolution-tests-run COMMAND capnp-evolution-tests) endif() # NOT CAPNP_LITE endif() # BUILD_TESTING if(DEFINED ENV{LIB_FUZZING_ENGINE}) add_executable(capnp_llvm_fuzzer_testcase llvm-fuzzer-testcase.c++ test-util.c++ test-util.h ${test_capnp_cpp_files} ${test_capnp_h_files}) target_link_libraries(capnp_llvm_fuzzer_testcase capnp-rpc capnp kj kj-async capnp-json $ENV{LIB_FUZZING_ENGINE}) endif() capnproto-c++-1.1.0/src/capnp/test-import.capnp0000644000175000017500000000237714527152321022157 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xf36d7b330303c66e; using Test = import "test.capnp"; struct TestImport { field @0 :Test.TestAllTypes; } capnproto-c++-1.1.0/src/capnp/encoding-test.c++0000644000175000017500000022773314712011043021676 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include #include #include "message.h" #include #include #include "test-util.h" #include "schema-lite.h" #include "serialize-packed.h" namespace capnp { namespace _ { // private namespace { TEST(Encoding, AllTypes) { MallocMessageBuilder builder; initTestMessage(builder.initRoot()); checkTestMessage(builder.getRoot()); checkTestMessage(builder.getRoot().asReader()); SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); checkTestMessage(reader.getRoot()); ASSERT_EQ(1u, builder.getSegmentsForOutput().size()); checkTestMessage(readMessageUnchecked(builder.getSegmentsForOutput()[0].begin())); EXPECT_EQ(builder.getSegmentsForOutput()[0].size() - 1, // -1 for root pointer reader.getRoot().totalSize().wordCount); } TEST(Encoding, AllTypesMultiSegment) { MallocMessageBuilder builder(0, AllocationStrategy::FIXED_SIZE); initTestMessage(builder.initRoot()); checkTestMessage(builder.getRoot()); checkTestMessage(builder.getRoot().asReader()); SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); checkTestMessage(reader.getRoot()); } TEST(Encoding, Defaults) { AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}}; kj::ArrayPtr segments[1] = {kj::arrayPtr(nullRoot.words, 1)}; SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); checkTestMessage(reader.getRoot()); checkTestMessage(readMessageUnchecked(nullRoot.words)); checkTestMessage(TestDefaults::Reader()); } TEST(Encoding, DefaultInitialization) { MallocMessageBuilder builder; checkTestMessage(builder.getRoot()); // first pass initializes to defaults checkTestMessage(builder.getRoot().asReader()); checkTestMessage(builder.getRoot()); // second pass just reads the initialized structure checkTestMessage(builder.getRoot().asReader()); SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); checkTestMessage(reader.getRoot()); } TEST(Encoding, DefaultInitializationMultiSegment) { MallocMessageBuilder builder(0, AllocationStrategy::FIXED_SIZE); // first pass initializes to defaults checkTestMessage(builder.getRoot()); checkTestMessage(builder.getRoot().asReader()); // second pass just reads the initialized structure checkTestMessage(builder.getRoot()); checkTestMessage(builder.getRoot().asReader()); SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); checkTestMessage(reader.getRoot()); } TEST(Encoding, DefaultsFromEmptyMessage) { AlignedData<1> emptyMessage = {{0, 0, 0, 0, 0, 0, 0, 0}}; kj::ArrayPtr segments[1] = {kj::arrayPtr(emptyMessage.words, 1)}; SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); checkTestMessage(reader.getRoot()); checkTestMessage(readMessageUnchecked(emptyMessage.words)); } TEST(Encoding, Unions) { MallocMessageBuilder builder; TestUnion::Builder root = builder.getRoot(); EXPECT_EQ(TestUnion::Union0::U0F0S0, root.getUnion0().which()); EXPECT_EQ(VOID, root.getUnion0().getU0f0s0()); EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s1()); root.getUnion0().setU0f0s1(true); EXPECT_EQ(TestUnion::Union0::U0F0S1, root.getUnion0().which()); EXPECT_TRUE(root.getUnion0().getU0f0s1()); EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s0()); root.getUnion0().setU0f0s8(123); EXPECT_EQ(TestUnion::Union0::U0F0S8, root.getUnion0().which()); EXPECT_EQ(123, root.getUnion0().getU0f0s8()); EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s1()); } struct UnionState { uint discriminants[4]; int dataOffset; UnionState(std::initializer_list discriminants, int dataOffset) : dataOffset(dataOffset) { memcpy(this->discriminants, discriminants.begin(), sizeof(this->discriminants)); } bool operator==(const UnionState& other) const { for (uint i = 0; i < 4; i++) { if (discriminants[i] != other.discriminants[i]) { return false; } } return dataOffset == other.dataOffset; } }; kj::String KJ_STRINGIFY(const UnionState& us) { return kj::str("UnionState({", kj::strArray(us.discriminants, ", "), "}, ", us.dataOffset, ")"); } template UnionState initUnion(Func&& initializer) { // Use the given setter to initialize the given union field and then return a struct indicating // the location of the data that was written as well as the values of the four union // discriminants. MallocMessageBuilder builder; initializer(builder.getRoot()); kj::ArrayPtr segment = builder.getSegmentsForOutput()[0]; KJ_ASSERT(segment.size() > 2, segment.size()); // Find the offset of the first set bit after the union discriminants. int offset = 0; for (const uint8_t* p = reinterpret_cast(segment.begin() + 2); p < reinterpret_cast(segment.end()); p++) { if (*p != 0) { uint8_t bits = *p; while ((bits & 1) == 0) { ++offset; bits >>= 1; } goto found; } offset += 8; } offset = -1; found: const uint8_t* discriminants = reinterpret_cast(segment.begin() + 1); return UnionState({discriminants[0], discriminants[2], discriminants[4], discriminants[6]}, offset); } TEST(Encoding, UnionLayout) { #define INIT_UNION(setter) \ initUnion([](TestUnion::Builder b) {b.setter;}) EXPECT_EQ(UnionState({ 0,0,0,0}, -1), INIT_UNION(getUnion0().setU0f0s0(VOID))); EXPECT_EQ(UnionState({ 1,0,0,0}, 0), INIT_UNION(getUnion0().setU0f0s1(1))); EXPECT_EQ(UnionState({ 2,0,0,0}, 0), INIT_UNION(getUnion0().setU0f0s8(1))); EXPECT_EQ(UnionState({ 3,0,0,0}, 0), INIT_UNION(getUnion0().setU0f0s16(1))); EXPECT_EQ(UnionState({ 4,0,0,0}, 0), INIT_UNION(getUnion0().setU0f0s32(1))); EXPECT_EQ(UnionState({ 5,0,0,0}, 0), INIT_UNION(getUnion0().setU0f0s64(1))); EXPECT_EQ(UnionState({ 6,0,0,0}, 448), INIT_UNION(getUnion0().setU0f0sp("1"))); EXPECT_EQ(UnionState({ 7,0,0,0}, -1), INIT_UNION(getUnion0().setU0f1s0(VOID))); EXPECT_EQ(UnionState({ 8,0,0,0}, 0), INIT_UNION(getUnion0().setU0f1s1(1))); EXPECT_EQ(UnionState({ 9,0,0,0}, 0), INIT_UNION(getUnion0().setU0f1s8(1))); EXPECT_EQ(UnionState({10,0,0,0}, 0), INIT_UNION(getUnion0().setU0f1s16(1))); EXPECT_EQ(UnionState({11,0,0,0}, 0), INIT_UNION(getUnion0().setU0f1s32(1))); EXPECT_EQ(UnionState({12,0,0,0}, 0), INIT_UNION(getUnion0().setU0f1s64(1))); EXPECT_EQ(UnionState({13,0,0,0}, 448), INIT_UNION(getUnion0().setU0f1sp("1"))); EXPECT_EQ(UnionState({0, 0,0,0}, -1), INIT_UNION(getUnion1().setU1f0s0(VOID))); EXPECT_EQ(UnionState({0, 1,0,0}, 65), INIT_UNION(getUnion1().setU1f0s1(1))); EXPECT_EQ(UnionState({0, 2,0,0}, 65), INIT_UNION(getUnion1().setU1f1s1(1))); EXPECT_EQ(UnionState({0, 3,0,0}, 72), INIT_UNION(getUnion1().setU1f0s8(1))); EXPECT_EQ(UnionState({0, 4,0,0}, 72), INIT_UNION(getUnion1().setU1f1s8(1))); EXPECT_EQ(UnionState({0, 5,0,0}, 80), INIT_UNION(getUnion1().setU1f0s16(1))); EXPECT_EQ(UnionState({0, 6,0,0}, 80), INIT_UNION(getUnion1().setU1f1s16(1))); EXPECT_EQ(UnionState({0, 7,0,0}, 96), INIT_UNION(getUnion1().setU1f0s32(1))); EXPECT_EQ(UnionState({0, 8,0,0}, 96), INIT_UNION(getUnion1().setU1f1s32(1))); EXPECT_EQ(UnionState({0, 9,0,0}, 128), INIT_UNION(getUnion1().setU1f0s64(1))); EXPECT_EQ(UnionState({0,10,0,0}, 128), INIT_UNION(getUnion1().setU1f1s64(1))); EXPECT_EQ(UnionState({0,11,0,0}, 512), INIT_UNION(getUnion1().setU1f0sp("1"))); EXPECT_EQ(UnionState({0,12,0,0}, 512), INIT_UNION(getUnion1().setU1f1sp("1"))); EXPECT_EQ(UnionState({0,13,0,0}, -1), INIT_UNION(getUnion1().setU1f2s0(VOID))); EXPECT_EQ(UnionState({0,14,0,0}, 65), INIT_UNION(getUnion1().setU1f2s1(1))); EXPECT_EQ(UnionState({0,15,0,0}, 72), INIT_UNION(getUnion1().setU1f2s8(1))); EXPECT_EQ(UnionState({0,16,0,0}, 80), INIT_UNION(getUnion1().setU1f2s16(1))); EXPECT_EQ(UnionState({0,17,0,0}, 96), INIT_UNION(getUnion1().setU1f2s32(1))); EXPECT_EQ(UnionState({0,18,0,0}, 128), INIT_UNION(getUnion1().setU1f2s64(1))); EXPECT_EQ(UnionState({0,19,0,0}, 512), INIT_UNION(getUnion1().setU1f2sp("1"))); EXPECT_EQ(UnionState({0,0,0,0}, 192), INIT_UNION(getUnion2().setU2f0s1(1))); EXPECT_EQ(UnionState({0,0,0,0}, 193), INIT_UNION(getUnion3().setU3f0s1(1))); EXPECT_EQ(UnionState({0,0,1,0}, 200), INIT_UNION(getUnion2().setU2f0s8(1))); EXPECT_EQ(UnionState({0,0,0,1}, 208), INIT_UNION(getUnion3().setU3f0s8(1))); EXPECT_EQ(UnionState({0,0,2,0}, 224), INIT_UNION(getUnion2().setU2f0s16(1))); EXPECT_EQ(UnionState({0,0,0,2}, 240), INIT_UNION(getUnion3().setU3f0s16(1))); EXPECT_EQ(UnionState({0,0,3,0}, 256), INIT_UNION(getUnion2().setU2f0s32(1))); EXPECT_EQ(UnionState({0,0,0,3}, 288), INIT_UNION(getUnion3().setU3f0s32(1))); EXPECT_EQ(UnionState({0,0,4,0}, 320), INIT_UNION(getUnion2().setU2f0s64(1))); EXPECT_EQ(UnionState({0,0,0,4}, 384), INIT_UNION(getUnion3().setU3f0s64(1))); #undef INIT_UNION } TEST(Encoding, UnnamedUnion) { MallocMessageBuilder builder; auto root = builder.initRoot(); EXPECT_EQ(test::TestUnnamedUnion::FOO, root.which()); root.setBar(321); EXPECT_EQ(test::TestUnnamedUnion::BAR, root.which()); EXPECT_EQ(test::TestUnnamedUnion::BAR, root.asReader().which()); EXPECT_EQ(321u, root.getBar()); EXPECT_EQ(321u, root.asReader().getBar()); EXPECT_DEBUG_ANY_THROW(root.getFoo()); EXPECT_DEBUG_ANY_THROW(root.asReader().getFoo()); root.setFoo(123); EXPECT_EQ(test::TestUnnamedUnion::FOO, root.which()); EXPECT_EQ(test::TestUnnamedUnion::FOO, root.asReader().which()); EXPECT_EQ(123u, root.getFoo()); EXPECT_EQ(123u, root.asReader().getFoo()); EXPECT_DEBUG_ANY_THROW(root.getBar()); EXPECT_DEBUG_ANY_THROW(root.asReader().getBar()); #if !CAPNP_LITE StructSchema schema = Schema::from(); // The discriminant is allocated just before allocating "bar". EXPECT_EQ(2u, schema.getProto().getStruct().getDiscriminantOffset()); EXPECT_EQ(0u, schema.getFieldByName("foo").getProto().getSlot().getOffset()); EXPECT_EQ(2u, schema.getFieldByName("bar").getProto().getSlot().getOffset()); #endif // !CAPNP_LITE } TEST(Encoding, Groups) { MallocMessageBuilder builder; auto root = builder.initRoot(); { auto foo = root.getGroups().initFoo(); foo.setCorge(12345678); foo.setGrault(123456789012345ll); foo.setGarply("foobar"); EXPECT_EQ(12345678, foo.getCorge()); EXPECT_EQ(123456789012345ll, foo.getGrault()); EXPECT_EQ("foobar", foo.getGarply()); } { auto bar = root.getGroups().initBar(); bar.setCorge(23456789); bar.setGrault("barbaz"); bar.setGarply(234567890123456ll); EXPECT_EQ(23456789, bar.getCorge()); EXPECT_EQ("barbaz", bar.getGrault()); EXPECT_EQ(234567890123456ll, bar.getGarply()); } { auto baz = root.getGroups().initBaz(); baz.setCorge(34567890); baz.setGrault("bazqux"); baz.setGarply("quxquux"); EXPECT_EQ(34567890, baz.getCorge()); EXPECT_EQ("bazqux", baz.getGrault()); EXPECT_EQ("quxquux", baz.getGarply()); } } TEST(Encoding, InterleavedGroups) { MallocMessageBuilder builder; auto root = builder.initRoot(); // Init both groups to different values. { auto group = root.getGroup1(); group.setFoo(12345678u); group.setBar(123456789012345llu); auto corge = group.initCorge(); corge.setGrault(987654321098765llu); corge.setGarply(12345u); corge.setPlugh("plugh"); corge.setXyzzy("xyzzy"); group.setWaldo("waldo"); } { auto group = root.getGroup2(); group.setFoo(23456789u); group.setBar(234567890123456llu); auto corge = group.initCorge(); corge.setGrault(876543210987654llu); corge.setGarply(23456u); corge.setPlugh("hgulp"); corge.setXyzzy("yzzyx"); group.setWaldo("odlaw"); } // Check group1 is still set correctly. { auto group = root.asReader().getGroup1(); EXPECT_EQ(12345678u, group.getFoo()); EXPECT_EQ(123456789012345llu, group.getBar()); auto corge = group.getCorge(); EXPECT_EQ(987654321098765llu, corge.getGrault()); EXPECT_EQ(12345u, corge.getGarply()); EXPECT_EQ("plugh", corge.getPlugh()); EXPECT_EQ("xyzzy", corge.getXyzzy()); EXPECT_EQ("waldo", group.getWaldo()); } // Zero out group 1 and see if it is zero'd. { auto group = root.initGroup1().asReader(); EXPECT_EQ(0u, group.getFoo()); EXPECT_EQ(0u, group.getBar()); EXPECT_EQ(test::TestInterleavedGroups::Group1::QUX, group.which()); EXPECT_EQ(0u, group.getQux()); EXPECT_FALSE(group.hasWaldo()); } // Group 2 should not have been touched. { auto group = root.asReader().getGroup2(); EXPECT_EQ(23456789u, group.getFoo()); EXPECT_EQ(234567890123456llu, group.getBar()); auto corge = group.getCorge(); EXPECT_EQ(876543210987654llu, corge.getGrault()); EXPECT_EQ(23456u, corge.getGarply()); EXPECT_EQ("hgulp", corge.getPlugh()); EXPECT_EQ("yzzyx", corge.getXyzzy()); EXPECT_EQ("odlaw", group.getWaldo()); } } TEST(Encoding, UnionDefault) { MallocMessageBuilder builder; TestUnionDefaults::Reader reader = builder.getRoot().asReader(); { auto field = reader.getS16s8s64s8Set(); EXPECT_EQ(TestUnion::Union0::U0F0S16, field.getUnion0().which()); EXPECT_EQ(TestUnion::Union1::U1F0S8 , field.getUnion1().which()); EXPECT_EQ(TestUnion::Union2::U2F0S64, field.getUnion2().which()); EXPECT_EQ(TestUnion::Union3::U3F0S8 , field.getUnion3().which()); EXPECT_EQ(321, field.getUnion0().getU0f0s16()); EXPECT_EQ(123, field.getUnion1().getU1f0s8()); EXPECT_EQ(12345678901234567ll, field.getUnion2().getU2f0s64()); EXPECT_EQ(55, field.getUnion3().getU3f0s8()); } { auto field = reader.getS0sps1s32Set(); EXPECT_EQ(TestUnion::Union0::U0F1S0 , field.getUnion0().which()); EXPECT_EQ(TestUnion::Union1::U1F0SP , field.getUnion1().which()); EXPECT_EQ(TestUnion::Union2::U2F0S1 , field.getUnion2().which()); EXPECT_EQ(TestUnion::Union3::U3F0S32, field.getUnion3().which()); EXPECT_EQ(VOID, field.getUnion0().getU0f1s0()); EXPECT_EQ("foo", field.getUnion1().getU1f0sp()); EXPECT_EQ(true, field.getUnion2().getU2f0s1()); EXPECT_EQ(12345678, field.getUnion3().getU3f0s32()); } { auto field = reader.getUnnamed1(); EXPECT_EQ(test::TestUnnamedUnion::FOO, field.which()); EXPECT_EQ(123u, field.getFoo()); EXPECT_FALSE(field.hasBefore()); EXPECT_FALSE(field.hasAfter()); } { auto field = reader.getUnnamed2(); EXPECT_EQ(test::TestUnnamedUnion::BAR, field.which()); EXPECT_EQ(321u, field.getBar()); EXPECT_EQ("foo", field.getBefore()); EXPECT_EQ("bar", field.getAfter()); } } // ======================================================================================= TEST(Encoding, ListDefaults) { MallocMessageBuilder builder; TestListDefaults::Builder root = builder.getRoot(); checkTestMessage(root.asReader()); checkTestMessage(root); checkTestMessage(root.asReader()); } TEST(Encoding, BuildListDefaults) { MallocMessageBuilder builder; TestListDefaults::Builder root = builder.getRoot(); initTestMessage(root); checkTestMessage(root.asReader()); checkTestMessage(root); checkTestMessage(root.asReader()); } TEST(Encoding, SmallStructLists) { // In this test, we will manually initialize TestListDefaults.lists to match the default // value and verify that we end up with the same encoding that the compiler produces. MallocMessageBuilder builder; auto root = builder.getRoot(); auto sl = root.initLists(); // Verify that all the lists are actually empty. EXPECT_EQ(0u, sl.getList0 ().size()); EXPECT_EQ(0u, sl.getList1 ().size()); EXPECT_EQ(0u, sl.getList8 ().size()); EXPECT_EQ(0u, sl.getList16().size()); EXPECT_EQ(0u, sl.getList32().size()); EXPECT_EQ(0u, sl.getList64().size()); EXPECT_EQ(0u, sl.getListP ().size()); EXPECT_EQ(0u, sl.getInt32ListList().size()); EXPECT_EQ(0u, sl.getTextListList().size()); EXPECT_EQ(0u, sl.getStructListList().size()); { auto l = sl.initList0 (2); l[0].setF(VOID); l[1].setF(VOID); } { auto l = sl.initList1 (4); l[0].setF(true); l[1].setF(false); l[2].setF(true); l[3].setF(true); } { auto l = sl.initList8 (2); l[0].setF(123u); l[1].setF(45u); } { auto l = sl.initList16(2); l[0].setF(12345u); l[1].setF(6789u); } { auto l = sl.initList32(2); l[0].setF(123456789u); l[1].setF(234567890u); } { auto l = sl.initList64(2); l[0].setF(1234567890123456u); l[1].setF(2345678901234567u); } { auto l = sl.initListP (2); l[0].setF("foo"); l[1].setF("bar"); } { auto l = sl.initInt32ListList(3); l.set(0, {1, 2, 3}); l.set(1, {4, 5}); l.set(2, {12341234}); } { auto l = sl.initTextListList(3); l.set(0, {"foo", "bar"}); l.set(1, {"baz"}); l.set(2, {"qux", "corge"}); } { auto l = sl.initStructListList(2); l.init(0, 2); l.init(1, 1); l[0][0].setInt32Field(123); l[0][1].setInt32Field(456); l[1][0].setInt32Field(789); } kj::ArrayPtr segment = builder.getSegmentsForOutput()[0]; // Initialize another message such that it copies the default value for that field. MallocMessageBuilder defaultBuilder; defaultBuilder.getRoot().getLists(); kj::ArrayPtr defaultSegment = defaultBuilder.getSegmentsForOutput()[0]; // Should match... EXPECT_EQ(defaultSegment.size(), segment.size()); for (size_t i = 0; i < kj::min(segment.size(), defaultSegment.size()); i++) { EXPECT_EQ(reinterpret_cast(defaultSegment.begin())[i], reinterpret_cast(segment.begin())[i]); } } TEST(Encoding, SetListToEmpty) { // Test initializing list fields from various ways of constructing zero-sized lists. // At one point this would often fail because the lists would have ElementSize::VOID which is // incompatible with other list sizes. #define ALL_LIST_TYPES(MACRO) \ MACRO(Void, Void) \ MACRO(Bool, bool) \ MACRO(UInt8, uint8_t) \ MACRO(UInt16, uint16_t) \ MACRO(UInt32, uint32_t) \ MACRO(UInt64, uint64_t) \ MACRO(Int8, int8_t) \ MACRO(Int16, int16_t) \ MACRO(Int32, int32_t) \ MACRO(Int64, int64_t) \ MACRO(Float32, float) \ MACRO(Float64, double) \ MACRO(Text, Text) \ MACRO(Data, Data) \ MACRO(Struct, TestAllTypes) #define SET_FROM_READER_ACCESSOR(name, type) \ root.set##name##List(reader.get##name##List()); #define SET_FROM_BUILDER_ACCESSOR(name, type) \ root.set##name##List(root.get##name##List()); #define SET_FROM_READER_CONSTRUCTOR(name, type) \ root.set##name##List(List::Reader()); #define SET_FROM_BUILDER_CONSTRUCTOR(name, type) \ root.set##name##List(List::Builder()); #define CHECK_EMPTY_NONNULL(name, type) \ EXPECT_TRUE(root.has##name##List()); \ EXPECT_EQ(0, root.get##name##List().size()); { MallocMessageBuilder builder; auto root = builder.initRoot(); auto reader = root.asReader(); ALL_LIST_TYPES(SET_FROM_READER_ACCESSOR) ALL_LIST_TYPES(CHECK_EMPTY_NONNULL) } { MallocMessageBuilder builder; auto root = builder.initRoot(); ALL_LIST_TYPES(SET_FROM_BUILDER_ACCESSOR) ALL_LIST_TYPES(CHECK_EMPTY_NONNULL) } { MallocMessageBuilder builder; auto root = builder.initRoot(); ALL_LIST_TYPES(SET_FROM_READER_CONSTRUCTOR) ALL_LIST_TYPES(CHECK_EMPTY_NONNULL) } { MallocMessageBuilder builder; auto root = builder.initRoot(); ALL_LIST_TYPES(SET_FROM_BUILDER_CONSTRUCTOR) ALL_LIST_TYPES(CHECK_EMPTY_NONNULL) } #undef SET_FROM_READER_ACCESSOR #undef SET_FROM_BUILDER_ACCESSOR #undef SET_FROM_READER_CONSTRUCTOR #undef SET_FROM_BUILDER_CONSTRUCTOR #undef CHECK_EMPTY_NONNULL } #if CAPNP_EXPENSIVE_TESTS TEST(Encoding, LongList) { // This test allocates 512MB of contiguous memory and takes several seconds, so we usually don't // run it. It is run before release, though. MallocMessageBuilder builder; auto root = builder.initRoot(); uint length = 1 << 27; auto list = root.initUInt64List(length); for (uint ii = 0; ii < length; ++ii) { list.set(ii, ii); } for (uint ii = 0; ii < length; ++ii) { ASSERT_EQ(list[ii], ii); } } #endif // ======================================================================================= TEST(Encoding, ListUpgrade) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({12, 34, 56}); checkList(root.getAnyPointerField().getAs>(), {12, 34, 56}); { auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(3u, l.size()); EXPECT_EQ(12u, l[0].getF()); EXPECT_EQ(34u, l[1].getF()); EXPECT_EQ(56u, l[2].getF()); } checkList(root.getAnyPointerField().getAs>(), {12, 34, 56}); auto reader = root.asReader(); checkList(reader.getAnyPointerField().getAs>(), {12, 34, 56}); { auto l = reader.getAnyPointerField().getAs>(); ASSERT_EQ(3u, l.size()); EXPECT_EQ(12u, l[0].getF()); EXPECT_EQ(34u, l[1].getF()); EXPECT_EQ(56u, l[2].getF()); } root.getAnyPointerField().setAs>({12, 34, 56}); { kj::Maybe e = kj::runCatchingExceptions([&]() { reader.getAnyPointerField().getAs>(); #if !KJ_NO_EXCEPTIONS ADD_FAILURE() << "Should have thrown an exception."; #endif }); KJ_EXPECT(e != nullptr, "Should have thrown an exception."); } { auto l = reader.getAnyPointerField().getAs>(); ASSERT_EQ(3u, l.size()); // These should return default values because the structs aren't big enough. EXPECT_EQ(0u, l[0].getF()); EXPECT_EQ(0u, l[1].getF()); EXPECT_EQ(0u, l[2].getF()); } checkList(reader.getAnyPointerField().getAs>(), {12, 34, 56}); } TEST(Encoding, BitListDowngrade) { // NO LONGER SUPPORTED -- We check for exceptions thrown. MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({0x1201u, 0x3400u, 0x5601u, 0x7801u}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); { auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_TRUE(l[0].getF()); EXPECT_FALSE(l[1].getF()); EXPECT_TRUE(l[2].getF()); EXPECT_TRUE(l[3].getF()); } checkList(root.getAnyPointerField().getAs>(), {0x1201u, 0x3400u, 0x5601u, 0x7801u}); auto reader = root.asReader(); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); { auto l = reader.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_TRUE(l[0].getF()); EXPECT_FALSE(l[1].getF()); EXPECT_TRUE(l[2].getF()); EXPECT_TRUE(l[3].getF()); } checkList(reader.getAnyPointerField().getAs>(), {0x1201u, 0x3400u, 0x5601u, 0x7801u}); } TEST(Encoding, BitListDowngradeFromStruct) { MallocMessageBuilder builder; auto root = builder.initRoot(); { auto list = root.getAnyPointerField().initAs>(4); list[0].setF(true); list[1].setF(false); list[2].setF(true); list[3].setF(true); } EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); { auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_TRUE(l[0].getF()); EXPECT_FALSE(l[1].getF()); EXPECT_TRUE(l[2].getF()); EXPECT_TRUE(l[3].getF()); } auto reader = root.asReader(); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); { auto l = reader.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_TRUE(l[0].getF()); EXPECT_FALSE(l[1].getF()); EXPECT_TRUE(l[2].getF()); EXPECT_TRUE(l[3].getF()); } } TEST(Encoding, BitListUpgrade) { // No longer supported! MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({true, false, true, true}); { kj::Maybe e = kj::runCatchingExceptions([&]() { root.getAnyPointerField().getAs>(); #if !KJ_NO_EXCEPTIONS ADD_FAILURE() << "Should have thrown an exception."; #endif }); KJ_EXPECT(e != nullptr, "Should have thrown an exception."); } auto reader = root.asReader(); { kj::Maybe e = kj::runCatchingExceptions([&]() { reader.getAnyPointerField().getAs>(); #if !KJ_NO_EXCEPTIONS ADD_FAILURE() << "Should have thrown an exception."; #endif }); KJ_EXPECT(e != nullptr, "Should have thrown an exception."); } } TEST(Encoding, UpgradeStructInBuilder) { MallocMessageBuilder builder; auto root = builder.initRoot(); test::TestOldVersion::Reader oldReader; { auto oldVersion = root.getAnyPointerField().initAs(); oldVersion.setOld1(123); oldVersion.setOld2("foo"); auto sub = oldVersion.initOld3(); sub.setOld1(456); sub.setOld2("bar"); oldReader = oldVersion; } size_t size = builder.getSegmentsForOutput()[0].size(); size_t size2; { auto newVersion = root.getAnyPointerField().getAs(); // The old instance should have been zero'd. EXPECT_EQ(0, oldReader.getOld1()); EXPECT_EQ("", oldReader.getOld2()); EXPECT_EQ(0, oldReader.getOld3().getOld1()); EXPECT_EQ("", oldReader.getOld3().getOld2()); // Size should have increased due to re-allocating the struct. size_t size1 = builder.getSegmentsForOutput()[0].size(); EXPECT_GT(size1, size); auto sub = newVersion.getOld3(); // Size should have increased due to re-allocating the sub-struct. size2 = builder.getSegmentsForOutput()[0].size(); EXPECT_GT(size2, size1); // Check contents. EXPECT_EQ(123, newVersion.getOld1()); EXPECT_EQ("foo", newVersion.getOld2()); EXPECT_EQ(987, newVersion.getNew1()); EXPECT_EQ("baz", newVersion.getNew2()); EXPECT_EQ(456, sub.getOld1()); EXPECT_EQ("bar", sub.getOld2()); EXPECT_EQ(987, sub.getNew1()); EXPECT_EQ("baz", sub.getNew2()); newVersion.setOld1(234); newVersion.setOld2("qux"); newVersion.setNew1(321); newVersion.setNew2("quux"); sub.setOld1(567); sub.setOld2("corge"); sub.setNew1(654); sub.setNew2("grault"); } // We set four small text fields and implicitly initialized two to defaults, so the size should // have raised by six words. size_t size3 = builder.getSegmentsForOutput()[0].size(); EXPECT_EQ(size2 + 6, size3); { // Go back to old version. It should have the values set on the new version. auto oldVersion = root.getAnyPointerField().getAs(); EXPECT_EQ(234, oldVersion.getOld1()); EXPECT_EQ("qux", oldVersion.getOld2()); auto sub = oldVersion.getOld3(); EXPECT_EQ(567, sub.getOld1()); EXPECT_EQ("corge", sub.getOld2()); // Overwrite the old fields. The new fields should remain intact. oldVersion.setOld1(345); oldVersion.setOld2("garply"); sub.setOld1(678); sub.setOld2("waldo"); } // We set two small text fields, so the size should have raised by two words. size_t size4 = builder.getSegmentsForOutput()[0].size(); EXPECT_EQ(size3 + 2, size4); { // Back to the new version again. auto newVersion = root.getAnyPointerField().getAs(); EXPECT_EQ(345, newVersion.getOld1()); EXPECT_EQ("garply", newVersion.getOld2()); EXPECT_EQ(321, newVersion.getNew1()); EXPECT_EQ("quux", newVersion.getNew2()); auto sub = newVersion.getOld3(); EXPECT_EQ(678, sub.getOld1()); EXPECT_EQ("waldo", sub.getOld2()); EXPECT_EQ(654, sub.getNew1()); EXPECT_EQ("grault", sub.getNew2()); } // Size should not have changed because we didn't write anything and the structs were already // the right size. EXPECT_EQ(size4, builder.getSegmentsForOutput()[0].size()); } TEST(Encoding, UpgradeStructInBuilderMultiSegment) { // Exactly like the previous test, except that we force multiple segments. Since we force a // separate segment for every object, every pointer is a far pointer, and far pointers are easily // transferred, so this is actually not such a complicated case. MallocMessageBuilder builder(0, AllocationStrategy::FIXED_SIZE); auto root = builder.initRoot(); // Start with a 1-word first segment and the root object in the second segment. size_t size = builder.getSegmentsForOutput().size(); EXPECT_EQ(2u, size); { auto oldVersion = root.getAnyPointerField().initAs(); oldVersion.setOld1(123); oldVersion.setOld2("foo"); auto sub = oldVersion.initOld3(); sub.setOld1(456); sub.setOld2("bar"); } // Allocated two structs and two strings. size_t size2 = builder.getSegmentsForOutput().size(); EXPECT_EQ(size + 4, size2); size_t size4; { auto newVersion = root.getAnyPointerField().getAs(); // Allocated a new struct. size_t size3 = builder.getSegmentsForOutput().size(); EXPECT_EQ(size2 + 1, size3); auto sub = newVersion.getOld3(); // Allocated another new struct for its string field. size4 = builder.getSegmentsForOutput().size(); EXPECT_EQ(size3 + 1, size4); // Check contents. EXPECT_EQ(123, newVersion.getOld1()); EXPECT_EQ("foo", newVersion.getOld2()); EXPECT_EQ(987, newVersion.getNew1()); EXPECT_EQ("baz", newVersion.getNew2()); EXPECT_EQ(456, sub.getOld1()); EXPECT_EQ("bar", sub.getOld2()); EXPECT_EQ(987, sub.getNew1()); EXPECT_EQ("baz", sub.getNew2()); newVersion.setOld1(234); newVersion.setOld2("qux"); newVersion.setNew1(321); newVersion.setNew2("quux"); sub.setOld1(567); sub.setOld2("corge"); sub.setNew1(654); sub.setNew2("grault"); } // Set four strings and implicitly initialized two. size_t size5 = builder.getSegmentsForOutput().size(); EXPECT_EQ(size4 + 6, size5); { // Go back to old version. It should have the values set on the new version. auto oldVersion = root.getAnyPointerField().getAs(); EXPECT_EQ(234, oldVersion.getOld1()); EXPECT_EQ("qux", oldVersion.getOld2()); auto sub = oldVersion.getOld3(); EXPECT_EQ(567, sub.getOld1()); EXPECT_EQ("corge", sub.getOld2()); // Overwrite the old fields. The new fields should remain intact. oldVersion.setOld1(345); oldVersion.setOld2("garply"); sub.setOld1(678); sub.setOld2("waldo"); } // Set two new strings. size_t size6 = builder.getSegmentsForOutput().size(); EXPECT_EQ(size5 + 2, size6); { // Back to the new version again. auto newVersion = root.getAnyPointerField().getAs(); EXPECT_EQ(345, newVersion.getOld1()); EXPECT_EQ("garply", newVersion.getOld2()); EXPECT_EQ(321, newVersion.getNew1()); EXPECT_EQ("quux", newVersion.getNew2()); auto sub = newVersion.getOld3(); EXPECT_EQ(678, sub.getOld1()); EXPECT_EQ("waldo", sub.getOld2()); EXPECT_EQ(654, sub.getNew1()); EXPECT_EQ("grault", sub.getNew2()); } // Size should not have changed because we didn't write anything and the structs were already // the right size. EXPECT_EQ(size6, builder.getSegmentsForOutput().size()); } TEST(Encoding, UpgradeStructInBuilderFarPointers) { // Force allocation of a Far pointer. MallocMessageBuilder builder(7, AllocationStrategy::FIXED_SIZE); auto root = builder.initRoot(); root.getAnyPointerField().initAs().setOld2("foo"); // We should have allocated all but one word of the first segment. EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); EXPECT_EQ(6u, builder.getSegmentsForOutput()[0].size()); // Now if we upgrade... EXPECT_EQ("foo", root.getAnyPointerField().getAs().getOld2()); // We should have allocated the new struct in a new segment, but allocated the far pointer // landing pad back in the first segment. ASSERT_EQ(2u, builder.getSegmentsForOutput().size()); EXPECT_EQ(7u, builder.getSegmentsForOutput()[0].size()); EXPECT_EQ(6u, builder.getSegmentsForOutput()[1].size()); } TEST(Encoding, UpgradeStructInBuilderDoubleFarPointers) { // Force allocation of a double-Far pointer. MallocMessageBuilder builder(6, AllocationStrategy::FIXED_SIZE); auto root = builder.initRoot(); root.getAnyPointerField().initAs().setOld2("foo"); // We should have allocated all of the first segment. EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); EXPECT_EQ(6u, builder.getSegmentsForOutput()[0].size()); // Now if we upgrade... EXPECT_EQ("foo", root.getAnyPointerField().getAs().getOld2()); // We should have allocated the new struct in a new segment, and also allocated the far pointer // landing pad in yet another segment. ASSERT_EQ(3u, builder.getSegmentsForOutput().size()); EXPECT_EQ(6u, builder.getSegmentsForOutput()[0].size()); EXPECT_EQ(6u, builder.getSegmentsForOutput()[1].size()); EXPECT_EQ(2u, builder.getSegmentsForOutput()[2].size()); } void checkUpgradedList(test::TestAnyPointer::Builder root, std::initializer_list expectedData, std::initializer_list expectedPointers) { { auto builder = root.getAnyPointerField().getAs>(); ASSERT_EQ(expectedData.size(), builder.size()); for (uint i = 0; i < expectedData.size(); i++) { EXPECT_EQ(expectedData.begin()[i], builder[i].getOld1()); EXPECT_EQ(expectedPointers.begin()[i], builder[i].getOld2()); // Other fields shouldn't be set. EXPECT_EQ(0, builder[i].asReader().getOld3().getOld1()); EXPECT_EQ("", builder[i].asReader().getOld3().getOld2()); EXPECT_EQ(987, builder[i].getNew1()); EXPECT_EQ("baz", builder[i].getNew2()); // Write some new data. builder[i].setOld1(i * 123); builder[i].setOld2(kj::str("qux", i, '\0').begin()); builder[i].setNew1(i * 456); builder[i].setNew2(kj::str("corge", i, '\0').begin()); } } // Read the newly-written data as TestOldVersion to ensure it was updated. { auto builder = root.getAnyPointerField().getAs>(); ASSERT_EQ(expectedData.size(), builder.size()); for (uint i = 0; i < expectedData.size(); i++) { EXPECT_EQ(i * 123, builder[i].getOld1()); EXPECT_EQ(Text::Reader(kj::str("qux", i, "\0").begin()), builder[i].getOld2()); } } // Also read back as TestNewVersion again. { auto builder = root.getAnyPointerField().getAs>(); ASSERT_EQ(expectedData.size(), builder.size()); for (uint i = 0; i < expectedData.size(); i++) { EXPECT_EQ(i * 123, builder[i].getOld1()); EXPECT_EQ(Text::Reader(kj::str("qux", i, '\0').begin()), builder[i].getOld2()); EXPECT_EQ(i * 456, builder[i].getNew1()); EXPECT_EQ(Text::Reader(kj::str("corge", i, '\0').begin()), builder[i].getNew2()); } } } TEST(Encoding, UpgradeListInBuilder) { // Test every damned list upgrade. MallocMessageBuilder builder; auto root = builder.initRoot(); // ----------------------------------------------------------------- root.getAnyPointerField().setAs>({VOID, VOID, VOID, VOID}); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkUpgradedList(root, {0, 0, 0, 0}, {"", "", "", ""}); // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({true, false, true, true}); auto orig = root.asReader().getAnyPointerField().getAs>(); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {true, false, true, true}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(orig, {true, false, true, true}); // Can't upgrade bit lists. (This used to be supported.) EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); } // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({0x12, 0x23, 0x33, 0x44}); auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0x12, 0x23, 0x33, 0x44}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(orig, {0x12, 0x23, 0x33, 0x44}); checkUpgradedList(root, {0x12, 0x23, 0x33, 0x44}, {"", "", "", ""}); checkList(orig, {0, 0, 0, 0}); // old location zero'd during upgrade } // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({0x5612, 0x7823, 0xab33, 0xcd44}); auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0x12, 0x23, 0x33, 0x44}); checkList(root.getAnyPointerField().getAs>(), {0x5612, 0x7823, 0xab33, 0xcd44}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(orig, {0x5612, 0x7823, 0xab33, 0xcd44}); checkUpgradedList(root, {0x5612, 0x7823, 0xab33, 0xcd44}, {"", "", "", ""}); checkList(orig, {0, 0, 0, 0}); // old location zero'd during upgrade } // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({0x17595612, 0x29347823, 0x5923ab32, 0x1a39cd45}); auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0x12, 0x23, 0x32, 0x45}); checkList(root.getAnyPointerField().getAs>(), {0x5612, 0x7823, 0xab32, 0xcd45}); checkList(root.getAnyPointerField().getAs>(), {0x17595612u, 0x29347823u, 0x5923ab32u, 0x1a39cd45u}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(orig, {0x17595612u, 0x29347823u, 0x5923ab32u, 0x1a39cd45u}); checkUpgradedList(root, {0x17595612, 0x29347823, 0x5923ab32, 0x1a39cd45}, {"", "", "", ""}); checkList(orig, {0u, 0u, 0u, 0u}); // old location zero'd during upgrade } // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({0x1234abcd8735fe21, 0x7173bc0e1923af36}); auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0x21, 0x36}); checkList(root.getAnyPointerField().getAs>(), {0xfe21, 0xaf36}); checkList(root.getAnyPointerField().getAs>(), {0x8735fe21u, 0x1923af36u}); checkList(root.getAnyPointerField().getAs>(), {0x1234abcd8735fe21ull, 0x7173bc0e1923af36ull}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(orig, {0x1234abcd8735fe21ull, 0x7173bc0e1923af36ull}); checkUpgradedList(root, {0x1234abcd8735fe21ull, 0x7173bc0e1923af36ull}, {"", ""}); checkList(orig, {0u, 0u}); // old location zero'd during upgrade } // ----------------------------------------------------------------- { root.getAnyPointerField().setAs>({"foo", "bar", "baz"}); auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {"foo", "bar", "baz"}); checkList(orig, {"foo", "bar", "baz"}); checkUpgradedList(root, {0, 0, 0}, {"foo", "bar", "baz"}); checkList(orig, {"", "", ""}); // old location zero'd during upgrade } // ----------------------------------------------------------------- { { auto l = root.getAnyPointerField().initAs>(3); l[0].setOld1(0x1234567890abcdef); l[1].setOld1(0x234567890abcdef1); l[2].setOld1(0x34567890abcdef12); l[0].setOld2("foo"); l[1].setOld2("bar"); l[2].setOld2("baz"); } auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(root.getAnyPointerField().getAs>(), {VOID, VOID, VOID}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0xefu, 0xf1u, 0x12u}); checkList(root.getAnyPointerField().getAs>(), {0xcdefu, 0xdef1u, 0xef12u}); checkList(root.getAnyPointerField().getAs>(), {0x90abcdefu, 0x0abcdef1u, 0xabcdef12u}); checkList(root.getAnyPointerField().getAs>(), {0x1234567890abcdefull, 0x234567890abcdef1ull, 0x34567890abcdef12ull}); checkList(root.getAnyPointerField().getAs>(), {"foo", "bar", "baz"}); checkList(orig, {0x1234567890abcdefull, 0x234567890abcdef1ull, 0x34567890abcdef12ull}, {"foo", "bar", "baz"}); checkUpgradedList(root, {0x1234567890abcdefull, 0x234567890abcdef1ull, 0x34567890abcdef12ull}, {"foo", "bar", "baz"}); checkList(orig, {0u, 0u, 0u}, {"", "", ""}); // old location zero'd during upgrade } // ----------------------------------------------------------------- // OK, now we've tested upgrading every primitive list to every primitive list, every primitive // list to a multi-word struct, and a multi-word struct to every primitive list. But we haven't // tried upgrading primitive lists to sub-word structs. // Upgrade from multi-byte, sub-word data. root.getAnyPointerField().setAs>({12u, 34u, 56u, 78u}); { auto orig = root.asReader().getAnyPointerField().getAs>(); checkList(orig, {12u, 34u, 56u, 78u}); auto l = root.getAnyPointerField().getAs>(); checkList(orig, {0u, 0u, 0u, 0u}); // old location zero'd during upgrade ASSERT_EQ(4u, l.size()); EXPECT_EQ(12u, l[0].getF()); EXPECT_EQ(34u, l[1].getF()); EXPECT_EQ(56u, l[2].getF()); EXPECT_EQ(78u, l[3].getF()); l[0].setF(0x65ac1235u); l[1].setF(0x13f12879u); l[2].setF(0x33423082u); l[3].setF(0x12988948u); } EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {0x35u, 0x79u, 0x82u, 0x48u}); checkList(root.getAnyPointerField().getAs>(), {0x1235u, 0x2879u, 0x3082u, 0x8948u}); checkList(root.getAnyPointerField().getAs>(), {0x65ac1235u, 0x13f12879u, 0x33423082u, 0x12988948u}); checkList(root.getAnyPointerField().getAs>(), {0x65ac1235u, 0x13f12879u, 0x33423082u, 0x12988948u}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); // Upgrade from void -> data struct root.getAnyPointerField().setAs>({VOID, VOID, VOID, VOID}); { auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_EQ(0u, l[0].getF()); EXPECT_EQ(0u, l[1].getF()); EXPECT_EQ(0u, l[2].getF()); EXPECT_EQ(0u, l[3].getF()); l[0].setF(12573); l[1].setF(3251); l[2].setF(9238); l[3].setF(5832); } EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {12573u, 3251u, 9238u, 5832u}); checkList(root.getAnyPointerField().getAs>(), {12573u, 3251u, 9238u, 5832u}); checkList(root.getAnyPointerField().getAs>(), {12573u, 3251u, 9238u, 5832u}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); // Upgrade from void -> pointer struct root.getAnyPointerField().setAs>({VOID, VOID, VOID, VOID}); { auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(4u, l.size()); EXPECT_EQ("", l[0].getF()); EXPECT_EQ("", l[1].getF()); EXPECT_EQ("", l[2].getF()); EXPECT_EQ("", l[3].getF()); l[0].setF("foo"); l[1].setF("bar"); l[2].setF("baz"); l[3].setF("qux"); } EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); checkList(root.getAnyPointerField().getAs>(), {"foo", "bar", "baz", "qux"}); // Verify that we cannot "side-grade" a pointer list to a data list, or a data list to // a pointer struct list. root.getAnyPointerField().setAs>({"foo", "bar", "baz", "qux"}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); root.getAnyPointerField().setAs>({12, 34, 56, 78}); EXPECT_NONFATAL_FAILURE(root.getAnyPointerField().getAs>()); } TEST(Encoding, UpgradeUnion) { // This tests for a specific case that was broken originally. MallocMessageBuilder builder; { auto root = builder.getRoot(); root.setB(123); } { auto root = builder.getRoot(); ASSERT_TRUE(root.isB()) EXPECT_EQ(123, root.getB()); } } // ======================================================================================= // Tests of generated code, not really of the encoding. // TODO(cleanup): Move to a different test? TEST(Encoding, NestedTypes) { // This is more of a test of the generated code than the encoding. MallocMessageBuilder builder; TestNestedTypes::Reader reader = builder.getRoot().asReader(); EXPECT_EQ(TestNestedTypes::NestedEnum::BAR, reader.getOuterNestedEnum()); EXPECT_EQ(TestNestedTypes::NestedStruct::NestedEnum::QUUX, reader.getInnerNestedEnum()); TestNestedTypes::NestedStruct::Reader nested = reader.getNestedStruct(); EXPECT_EQ(TestNestedTypes::NestedEnum::BAR, nested.getOuterNestedEnum()); EXPECT_EQ(TestNestedTypes::NestedStruct::NestedEnum::QUUX, nested.getInnerNestedEnum()); } TEST(Encoding, Imports) { // Also just testing the generated code. { MallocMessageBuilder builder; TestImport::Builder root = builder.getRoot(); initTestMessage(root.initField()); checkTestMessage(root.asReader().getField()); } { MallocMessageBuilder builder; TestImport2::Builder root = builder.getRoot(); initTestMessage(root.initFoo()); checkTestMessage(root.asReader().getFoo()); root.setBar(schemaProto()); initTestMessage(root.initBaz().initField()); checkTestMessage(root.asReader().getBaz().getField()); } } TEST(Encoding, Using) { MallocMessageBuilder builder; TestUsing::Reader reader = builder.getRoot().asReader(); EXPECT_EQ(TestNestedTypes::NestedEnum::BAR, reader.getOuterNestedEnum()); EXPECT_EQ(TestNestedTypes::NestedStruct::NestedEnum::QUUX, reader.getInnerNestedEnum()); } TEST(Encoding, StructSetters) { MallocMessageBuilder builder; auto root = builder.getRoot(); initTestMessage(root); { MallocMessageBuilder builder2; builder2.setRoot(root.asReader()); checkTestMessage(builder2.getRoot()); } { MallocMessageBuilder builder2; auto root2 = builder2.getRoot(); root2.setStructField(root); checkTestMessage(root2.getStructField()); } { MallocMessageBuilder builder2; auto root2 = builder2.getRoot(); root2.getAnyPointerField().setAs(root); checkTestMessage(root2.getAnyPointerField().getAs()); } } TEST(Encoding, OneBitStructSetters) { // Test case of setting a 1-bit struct. MallocMessageBuilder builder; auto root = builder.getRoot(); auto list = root.initList1(8); list[0].setF(true); list[1].setF(true); list[2].setF(false); list[3].setF(true); list[4].setF(true); list[5].setF(false); list[6].setF(true); list[7].setF(false); MallocMessageBuilder builder2; builder2.setRoot(list.asReader()[2]); EXPECT_FALSE(builder2.getRoot().getF()); builder2.setRoot(list.asReader()[6]); EXPECT_TRUE(builder2.getRoot().getF()); } TEST(Encoding, ListSetters) { MallocMessageBuilder builder; auto root = builder.getRoot(); initTestMessage(root); { MallocMessageBuilder builder2; auto root2 = builder2.getRoot(); root2.getLists().setList0(root.getLists().getList0()); root2.getLists().setList1(root.getLists().getList1()); root2.getLists().setList8(root.getLists().getList8()); root2.getLists().setList16(root.getLists().getList16()); root2.getLists().setList32(root.getLists().getList32()); root2.getLists().setList64(root.getLists().getList64()); root2.getLists().setListP(root.getLists().getListP()); { auto dst = root2.getLists().initInt32ListList(3); auto src = root.getLists().getInt32ListList(); dst.set(0, src[0]); dst.set(1, src[1]); dst.set(2, src[2]); } { auto dst = root2.getLists().initTextListList(3); auto src = root.getLists().getTextListList(); dst.set(0, src[0]); dst.set(1, src[1]); dst.set(2, src[2]); } { auto dst = root2.getLists().initStructListList(2); auto src = root.getLists().getStructListList(); dst.set(0, src[0]); dst.set(1, src[1]); } checkTestMessage(root2); // Now let's do some adopting and disowning. auto adopter = builder2.getOrphanage().newOrphan(); auto disowner = root2.disownLists(); adopter.get().adoptList0(disowner.get().disownList0()); adopter.get().adoptList1(disowner.get().disownList1()); adopter.get().adoptList8(disowner.get().disownList8()); adopter.get().adoptList16(disowner.get().disownList16()); adopter.get().adoptList32(disowner.get().disownList32()); adopter.get().adoptList64(disowner.get().disownList64()); adopter.get().adoptListP(disowner.get().disownListP()); { auto dst = adopter.get().initInt32ListList(3); auto src = disowner.get().getInt32ListList(); auto orphan = src.disown(0); checkList(orphan.getReader(), {1, 2, 3}); dst.adopt(0, kj::mv(orphan)); dst.adopt(1, src.disown(1)); dst.adopt(2, src.disown(2)); } { auto dst = adopter.get().initTextListList(3); auto src = disowner.get().getTextListList(); auto orphan = src.disown(0); checkList(orphan.getReader(), {"foo", "bar"}); dst.adopt(0, kj::mv(orphan)); dst.adopt(1, src.disown(1)); dst.adopt(2, src.disown(2)); } { auto dst = adopter.get().initStructListList(2); auto src = disowner.get().getStructListList(); auto orphan = src.disown(0); KJ_EXPECT(orphan.getReader()[0].getInt32Field() == 123); KJ_EXPECT(orphan.getReader()[1].getInt32Field() == 456); dst.adopt(0, kj::mv(orphan)); dst.adopt(1, src.disown(1)); } root2.adoptLists(kj::mv(adopter)); checkTestMessage(root2); } } TEST(Encoding, ZeroOldObject) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); auto oldRoot = root.asReader(); checkTestMessage(oldRoot); auto oldSub = oldRoot.getStructField(); auto oldSub2 = oldRoot.getStructList()[0]; root = builder.initRoot(); checkTestMessageAllZero(oldRoot); checkTestMessageAllZero(oldSub); checkTestMessageAllZero(oldSub2); } TEST(Encoding, Has) { MallocMessageBuilder builder; auto root = builder.initRoot(); EXPECT_FALSE(root.hasTextField()); EXPECT_FALSE(root.hasDataField()); EXPECT_FALSE(root.hasStructField()); EXPECT_FALSE(root.hasInt32List()); EXPECT_FALSE(root.asReader().hasTextField()); EXPECT_FALSE(root.asReader().hasDataField()); EXPECT_FALSE(root.asReader().hasStructField()); EXPECT_FALSE(root.asReader().hasInt32List()); initTestMessage(root); EXPECT_TRUE(root.hasTextField()); EXPECT_TRUE(root.hasDataField()); EXPECT_TRUE(root.hasStructField()); EXPECT_TRUE(root.hasInt32List()); EXPECT_TRUE(root.asReader().hasTextField()); EXPECT_TRUE(root.asReader().hasDataField()); EXPECT_TRUE(root.asReader().hasStructField()); EXPECT_TRUE(root.asReader().hasInt32List()); } TEST(Encoding, VoidListAmplification) { MallocMessageBuilder builder; builder.initRoot().getAnyPointerField().initAs>(1u << 28); auto segments = builder.getSegmentsForOutput(); EXPECT_EQ(1, segments.size()); EXPECT_LT(segments[0].size(), 16); // quite small for such a big list! SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); auto root = reader.getRoot().getAnyPointerField(); EXPECT_NONFATAL_FAILURE(root.getAs>()); MallocMessageBuilder copy; EXPECT_NONFATAL_FAILURE(copy.setRoot(reader.getRoot())); } TEST(Encoding, EmptyStructListAmplification) { MallocMessageBuilder builder(1024); auto listList = builder.initRoot().getAnyPointerField() .initAs>>(500); for (uint i = 0; i < listList.size(); i++) { listList.init(i, 1u << 28); } auto segments = builder.getSegmentsForOutput(); ASSERT_EQ(1, segments.size()); SegmentArrayMessageReader reader(builder.getSegmentsForOutput()); auto root = reader.getRoot(); auto listListReader = root.getAnyPointerField().getAs>>(); EXPECT_NONFATAL_FAILURE(listListReader[0]); EXPECT_NONFATAL_FAILURE(listListReader[10]); EXPECT_EQ(segments[0].size() - 1, root.totalSize().wordCount); } TEST(Encoding, Constants) { EXPECT_EQ(VOID, test::TestConstants::VOID_CONST); EXPECT_EQ(true, test::TestConstants::BOOL_CONST); EXPECT_EQ(-123, test::TestConstants::INT8_CONST); EXPECT_EQ(-12345, test::TestConstants::INT16_CONST); EXPECT_EQ(-12345678, test::TestConstants::INT32_CONST); EXPECT_EQ(-123456789012345ll, test::TestConstants::INT64_CONST); EXPECT_EQ(234u, test::TestConstants::UINT8_CONST); EXPECT_EQ(45678u, test::TestConstants::UINT16_CONST); EXPECT_EQ(3456789012u, test::TestConstants::UINT32_CONST); EXPECT_EQ(12345678901234567890ull, test::TestConstants::UINT64_CONST); EXPECT_FLOAT_EQ(1234.5f, test::TestConstants::FLOAT32_CONST); EXPECT_DOUBLE_EQ(-123e45, test::TestConstants::FLOAT64_CONST); EXPECT_EQ("foo", *test::TestConstants::TEXT_CONST); EXPECT_EQ(data("bar"), test::TestConstants::DATA_CONST); { TestAllTypes::Reader subReader = test::TestConstants::STRUCT_CONST; EXPECT_EQ(VOID, subReader.getVoidField()); EXPECT_EQ(true, subReader.getBoolField()); EXPECT_EQ(-12, subReader.getInt8Field()); EXPECT_EQ(3456, subReader.getInt16Field()); EXPECT_EQ(-78901234, subReader.getInt32Field()); EXPECT_EQ(56789012345678ll, subReader.getInt64Field()); EXPECT_EQ(90u, subReader.getUInt8Field()); EXPECT_EQ(1234u, subReader.getUInt16Field()); EXPECT_EQ(56789012u, subReader.getUInt32Field()); EXPECT_EQ(345678901234567890ull, subReader.getUInt64Field()); EXPECT_FLOAT_EQ(-1.25e-10f, subReader.getFloat32Field()); EXPECT_DOUBLE_EQ(345, subReader.getFloat64Field()); EXPECT_EQ("baz", subReader.getTextField()); EXPECT_EQ(data("qux"), subReader.getDataField()); { auto subSubReader = subReader.getStructField(); EXPECT_EQ("nested", subSubReader.getTextField()); EXPECT_EQ("really nested", subSubReader.getStructField().getTextField()); } EXPECT_EQ(TestEnum::BAZ, subReader.getEnumField()); checkList(subReader.getVoidList(), {VOID, VOID, VOID}); checkList(subReader.getBoolList(), {false, true, false, true, true}); checkList(subReader.getInt8List(), {12, -34, -0x80, 0x7f}); checkList(subReader.getInt16List(), {1234, -5678, -0x8000, 0x7fff}); // gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1. checkList(subReader.getInt32List(), {12345678, -90123456, -0x7fffffff - 1, 0x7fffffff}); checkList(subReader.getInt64List(), {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll}); checkList(subReader.getUInt8List(), {12u, 34u, 0u, 0xffu}); checkList(subReader.getUInt16List(), {1234u, 5678u, 0u, 0xffffu}); checkList(subReader.getUInt32List(), {12345678u, 90123456u, 0u, 0xffffffffu}); checkList(subReader.getUInt64List(), {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull}); checkList(subReader.getFloat32List(), {0.0f, 1234567.0f, 1e37f, -1e37f, 1e-37f, -1e-37f}); checkList(subReader.getFloat64List(), {0.0, 123456789012345.0, 1e306, -1e306, 1e-306, -1e-306}); checkList(subReader.getTextList(), {"quux", "corge", "grault"}); checkList(subReader.getDataList(), {data("garply"), data("waldo"), data("fred")}); { auto listReader = subReader.getStructList(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("x structlist 1", listReader[0].getTextField()); EXPECT_EQ("x structlist 2", listReader[1].getTextField()); EXPECT_EQ("x structlist 3", listReader[2].getTextField()); } checkList(subReader.getEnumList(), {TestEnum::QUX, TestEnum::BAR, TestEnum::GRAULT}); } EXPECT_EQ(TestEnum::CORGE, test::TestConstants::ENUM_CONST); EXPECT_EQ(6u, test::TestConstants::VOID_LIST_CONST->size()); checkList(*test::TestConstants::BOOL_LIST_CONST, {true, false, false, true}); checkList(*test::TestConstants::INT8_LIST_CONST, {111, -111}); checkList(*test::TestConstants::INT16_LIST_CONST, {11111, -11111}); checkList(*test::TestConstants::INT32_LIST_CONST, {111111111, -111111111}); checkList(*test::TestConstants::INT64_LIST_CONST, {1111111111111111111ll, -1111111111111111111ll}); checkList(*test::TestConstants::UINT8_LIST_CONST, {111u, 222u}); checkList(*test::TestConstants::UINT16_LIST_CONST, {33333u, 44444u}); checkList(*test::TestConstants::UINT32_LIST_CONST, {3333333333u}); checkList(*test::TestConstants::UINT64_LIST_CONST, {11111111111111111111ull}); { List::Reader listReader = test::TestConstants::FLOAT32_LIST_CONST; ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(5555.5f, listReader[0]); EXPECT_EQ(kj::inf(), listReader[1]); EXPECT_EQ(-kj::inf(), listReader[2]); EXPECT_TRUE(listReader[3] != listReader[3]); } { List::Reader listReader = test::TestConstants::FLOAT64_LIST_CONST; ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(7777.75, listReader[0]); EXPECT_EQ(kj::inf(), listReader[1]); EXPECT_EQ(-kj::inf(), listReader[2]); EXPECT_TRUE(listReader[3] != listReader[3]); } checkList(*test::TestConstants::TEXT_LIST_CONST, {"plugh", "xyzzy", "thud"}); checkList(*test::TestConstants::DATA_LIST_CONST, {data("oops"), data("exhausted"), data("rfc3092")}); { List::Reader listReader = test::TestConstants::STRUCT_LIST_CONST; ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("structlist 1", listReader[0].getTextField()); EXPECT_EQ("structlist 2", listReader[1].getTextField()); EXPECT_EQ("structlist 3", listReader[2].getTextField()); } checkList(*test::TestConstants::ENUM_LIST_CONST, {TestEnum::FOO, TestEnum::GARPLY}); } TEST(Encoding, AnyPointerConstants) { auto reader = test::ANY_POINTER_CONSTANTS.get(); EXPECT_EQ("baz", reader.getAnyKindAsStruct().getAs().getTextField()); EXPECT_EQ("baz", reader.getAnyStructAsStruct().as().getTextField()); EXPECT_EQ(111111111, reader.getAnyKindAsList().getAs>()[0]); EXPECT_EQ(111111111, reader.getAnyListAsList().as>()[0]); } TEST(Encoding, GlobalConstants) { EXPECT_EQ(12345u, test::GLOBAL_INT); EXPECT_EQ("foobar", test::GLOBAL_TEXT.get()); EXPECT_EQ(54321, test::GLOBAL_STRUCT->getInt32Field()); TestAllTypes::Reader reader = test::DERIVED_CONSTANT; EXPECT_EQ(12345, reader.getUInt32Field()); EXPECT_EQ("foo", reader.getTextField()); checkList(reader.getStructField().getTextList(), {"quux", "corge", "grault"}); checkList(reader.getInt16List(), {11111, -11111}); { List::Reader listReader = reader.getStructList(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("structlist 1", listReader[0].getTextField()); EXPECT_EQ("structlist 2", listReader[1].getTextField()); EXPECT_EQ("structlist 3", listReader[2].getTextField()); } kj::StringPtr expected = "foo bar baz\n" "\"qux\" `corge` \'grault\'\n" "regular\"quoted\"line" "garply\\nwaldo\\tfred\\\"plugh\\\"xyzzy\\\'thud\n"; EXPECT_EQ(expected, test::BLOCK_TEXT); } TEST(Encoding, Embeds) { { kj::ArrayInputStream input(test::EMBEDDED_DATA); PackedMessageReader reader(input); checkTestMessage(reader.getRoot()); } #if !CAPNP_LITE { MallocMessageBuilder builder; auto root = builder.getRoot(); initTestMessage(root); kj::StringPtr text = test::EMBEDDED_TEXT; EXPECT_EQ(kj::str(root, text.endsWith("\r\n") ? "\r\n" : "\n"), text); } #endif // CAPNP_LITE { checkTestMessage(test::EMBEDDED_STRUCT); } } TEST(Encoding, HasEmptyStruct) { MallocMessageBuilder message; auto root = message.initRoot(); EXPECT_EQ(1, root.totalSize().wordCount); EXPECT_FALSE(root.asReader().hasAnyPointerField()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().initAs(); EXPECT_TRUE(root.asReader().hasAnyPointerField()); EXPECT_TRUE(root.hasAnyPointerField()); EXPECT_EQ(1, root.totalSize().wordCount); } TEST(Encoding, HasEmptyList) { MallocMessageBuilder message; auto root = message.initRoot(); EXPECT_EQ(1, root.totalSize().wordCount); EXPECT_FALSE(root.asReader().hasAnyPointerField()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().initAs>(0); EXPECT_TRUE(root.asReader().hasAnyPointerField()); EXPECT_TRUE(root.hasAnyPointerField()); EXPECT_EQ(1, root.totalSize().wordCount); } TEST(Encoding, HasEmptyStructList) { MallocMessageBuilder message; auto root = message.initRoot(); EXPECT_EQ(1, root.totalSize().wordCount); EXPECT_FALSE(root.asReader().hasAnyPointerField()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().initAs>(0); EXPECT_TRUE(root.asReader().hasAnyPointerField()); EXPECT_TRUE(root.hasAnyPointerField()); EXPECT_EQ(2, root.totalSize().wordCount); } TEST(Encoding, NameAnnotation) { EXPECT_EQ(2, static_cast(test::RenamedStruct::RenamedEnum::QUX)); EXPECT_EQ(2, static_cast(test::RenamedStruct::RenamedNestedStruct::RenamedDeeplyNestedEnum::GARPLY)); MallocMessageBuilder message; auto root = message.initRoot(); root.setGoodFieldName(true); EXPECT_EQ(true, root.getGoodFieldName()); EXPECT_TRUE(root.isGoodFieldName()); root.setBar(0xff); EXPECT_FALSE(root.isGoodFieldName()); root.setAnotherGoodFieldName(test::RenamedStruct::RenamedEnum::QUX); EXPECT_EQ(test::RenamedStruct::RenamedEnum::QUX, root.getAnotherGoodFieldName()); EXPECT_FALSE(root.getRenamedUnion().isQux()); auto quxBuilder = root.getRenamedUnion().initQux(); EXPECT_TRUE(root.getRenamedUnion().isQux()); EXPECT_FALSE(root.getRenamedUnion().getQux().hasAnotherGoodNestedFieldName()); quxBuilder.setGoodNestedFieldName(true); EXPECT_EQ(true, quxBuilder.getGoodNestedFieldName()); EXPECT_FALSE(quxBuilder.hasAnotherGoodNestedFieldName()); auto nestedFieldBuilder = quxBuilder.initAnotherGoodNestedFieldName(); EXPECT_TRUE(quxBuilder.hasAnotherGoodNestedFieldName()); nestedFieldBuilder.setGoodNestedFieldName(true); EXPECT_EQ(true, nestedFieldBuilder.getGoodNestedFieldName()); EXPECT_FALSE(nestedFieldBuilder.hasAnotherGoodNestedFieldName()); EXPECT_FALSE(root.getRenamedUnion().isRenamedGroup()); auto renamedGroupBuilder KJ_UNUSED = root.getRenamedUnion().initRenamedGroup(); EXPECT_TRUE(root.getRenamedUnion().isRenamedGroup()); test::RenamedInterface::RenamedMethodParams::Reader renamedInterfaceParams; renamedInterfaceParams.getRenamedParam(); } TEST(Encoding, DefaultFloatPlusNan) { MallocMessageBuilder message; auto root = message.initRoot(); root.setFloat32Field(kj::nan()); root.setFloat64Field(kj::nan()); float f = root.getFloat32Field(); EXPECT_TRUE(f != f); double d = root.getFloat64Field(); EXPECT_TRUE(d != d); } TEST(Encoding, WholeFloatDefault) { MallocMessageBuilder message; auto root = message.initRoot(); EXPECT_EQ(123.0f, root.getField()); EXPECT_EQ(2e30f, root.getBigField()); EXPECT_EQ(456.0f, test::TestWholeFloatDefault::CONSTANT); EXPECT_EQ(4e30f, test::TestWholeFloatDefault::BIG_CONSTANT); } TEST(Encoding, Generics) { MallocMessageBuilder message; auto root = message.initRoot(); auto reader = root.asReader(); initTestMessage(root.initBasic().initFoo()); checkTestMessage(reader.getBasic().getFoo()); { auto typed = root.getBasic(); test::TestGenerics<>::Reader generic = typed.asGeneric<>(); checkTestMessage(generic.getFoo().getAs()); test::TestGenerics::Reader halfGeneric = typed.asGeneric(); checkTestMessage(halfGeneric.getFoo()); } { auto typed = root.getBasic().asReader(); test::TestGenerics<>::Reader generic = typed.asGeneric<>(); checkTestMessage(generic.getFoo().getAs()); test::TestGenerics::Reader halfGeneric = typed.asGeneric(); checkTestMessage(halfGeneric.getFoo()); } initTestMessage(root.initInner().initFoo()); checkTestMessage(reader.getInner().getFoo()); { auto typed = root.getInner(); test::TestGenerics<>::Inner::Reader generic = typed.asTestGenericsGeneric<>(); checkTestMessage(generic.getFoo().getAs()); test::TestGenerics::Inner::Reader halfGeneric = typed.asTestGenericsGeneric(); checkTestMessage(halfGeneric.getFoo()); } { auto typed = root.getInner().asReader(); test::TestGenerics<>::Inner::Reader generic = typed.asTestGenericsGeneric<>(); checkTestMessage(generic.getFoo().getAs()); test::TestGenerics::Inner::Reader halfGeneric = typed.asTestGenericsGeneric(); checkTestMessage(halfGeneric.getFoo()); } root.initInner2().setBaz("foo"); EXPECT_EQ("foo", reader.getInner2().getBaz()); initTestMessage(root.getInner2().initInnerBound().initFoo()); checkTestMessage(reader.getInner2().getInnerBound().getFoo()); initTestMessage(root.getInner2().initInnerUnbound().getFoo().initAs()); checkTestMessage(reader.getInner2().getInnerUnbound().getFoo().getAs()); initTestMessage(root.initUnspecified().getFoo().initAs()); checkTestMessage(reader.getUnspecified().getFoo().getAs()); initTestMessage(root.initWrapper().initValue().initFoo()); checkTestMessage(reader.getWrapper().getValue().getFoo()); } TEST(Encoding, GenericDefaults) { test::TestUseGenerics::Reader reader; EXPECT_EQ(123, reader.getDefault().getFoo().getInt16Field()); EXPECT_EQ(123, reader.getDefaultInner().getFoo().getInt16Field()); EXPECT_EQ("text", reader.getDefaultInner().getBar()); EXPECT_EQ(123, reader.getDefaultUser().getBasic().getFoo().getInt16Field()); EXPECT_EQ("text", reader.getDefaultWrapper().getValue().getFoo()); EXPECT_EQ(321, reader.getDefaultWrapper().getValue().getRev().getFoo().getInt16Field()); EXPECT_EQ("text", reader.getDefaultWrapper2().getValue().getValue().getFoo()); EXPECT_EQ(321, reader.getDefaultWrapper2().getValue() .getValue().getRev().getFoo().getInt16Field()); } TEST(Encoding, UnionInGenerics) { MallocMessageBuilder message; auto builder = message.initRoot>(); auto reader = builder.asReader(); //just call the methods to verify that generated code compiles reader.which(); builder.which(); reader.isUv(); builder.isUv(); reader.getUv(); builder.getUv(); builder.setUv(); builder.initUg(); reader.isUg(); builder.isUg(); reader.getUg(); builder.getUg(); builder.initUg(); } TEST(Encoding, DefaultListBuilder) { // At one point, this wouldn't compile. List::Builder(nullptr); List::Builder(nullptr); List>::Builder(nullptr); List::Builder(nullptr); } TEST(Encoding, ListSize) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); auto lists = root.asReader().getLists(); auto listSizes = lists.getList0().totalSize() + lists.getList1().totalSize() + lists.getList8().totalSize() + lists.getList16().totalSize() + lists.getList32().totalSize() + lists.getList64().totalSize() + lists.getListP().totalSize() + lists.getInt32ListList().totalSize() + lists.getTextListList().totalSize() + lists.getStructListList().totalSize(); auto structSize = lists.totalSize(); auto shallowSize = unbound(capnp::_::structSize().total() / WORDS); EXPECT_EQ(structSize.wordCount - shallowSize, listSizes.wordCount); } KJ_TEST("list.setWithCaveats(i, list[i]) doesn't corrupt contents") { MallocMessageBuilder builder; auto root = builder.initRoot(); auto list = root.initStructList(2); initTestMessage(list[0]); list.setWithCaveats(0, list[0]); checkTestMessage(list[0]); checkTestMessageAllZero(list[1]); list.setWithCaveats(1, list[0]); checkTestMessage(list[0]); checkTestMessage(list[1]); } KJ_TEST("Downgrade pointer-list from struct-list") { // Test that downgrading a list-of-structs to a list-of-pointers (where the relevant pointer is // the struct's first pointer) works as advertised. MallocMessageBuilder builder; auto root = builder.initRoot(); { auto list = root.getAnyPointerField().initAs>(2); initTestMessage(list[0]); list[1].setTextField("hello"); } { auto list = root.asReader().getAnyPointerField().getAs>(); KJ_ASSERT(list.size() == 2); KJ_EXPECT(list[0] == "foo"); KJ_EXPECT(list[1] == "hello"); } } KJ_TEST("Copying ListList downgraded from ListStruct does not get corrupted") { // Test written by David Renshaw to demonstrate CVE-??? AlignedData<10> data = {{ // struct, 1 pointer 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // list, inline composite. 4 words. 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, // one element, 3 data words, 1 pointer. 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, // data section 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, // data section 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, // data section 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // null struct pointer // bad bytes that shouldn't be visible from the root of the message 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, // bug can cause this word to be read as the list element struct pointer 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; kj::ArrayPtr segments[1] = { // Only take the first 7 words. The last three words above should not be accessible // from these segments. kj::arrayPtr(data.words, 7) }; SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); auto readerRoot = reader.getRoot(); auto listList = readerRoot.getAnyPointerField().getAs>>(); EXPECT_EQ(listList.size(), 1); MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>>(listList); auto outputSegments = builder.getSegmentsForOutput(); ASSERT_EQ(outputSegments.size(), 1); auto inputBytes = segments[0].asBytes(); auto outputBytes = outputSegments[0].asBytes(); ASSERT_EQ(outputBytes, inputBytes); // Should be equal. Instead, we see that outputBytes includes the (copied) // out-of-bounds 0xbb bytes from `data` above, which should be impossible. } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc.capnp.c++0000644000175000017500000027634514712011043021022 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: rpc.capnp #include "rpc.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<232> b_91b79f1f808db032 = { { 0, 0, 0, 0, 5, 0, 6, 0, 50, 176, 141, 128, 31, 159, 183, 145, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 23, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 77, 101, 115, 115, 97, 103, 101, 0, 0, 0, 0, 0, 1, 0, 1, 0, 56, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 1, 0, 0, 3, 0, 1, 0, 132, 1, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 1, 0, 0, 3, 0, 1, 0, 136, 1, 0, 0, 2, 0, 1, 0, 3, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 1, 0, 0, 3, 0, 1, 0, 140, 1, 0, 0, 2, 0, 1, 0, 4, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 1, 0, 0, 3, 0, 1, 0, 144, 1, 0, 0, 2, 0, 1, 0, 5, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 1, 0, 0, 3, 0, 1, 0, 148, 1, 0, 0, 2, 0, 1, 0, 6, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 1, 0, 0, 3, 0, 1, 0, 152, 1, 0, 0, 2, 0, 1, 0, 7, 0, 249, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 3, 0, 1, 0, 156, 1, 0, 0, 2, 0, 1, 0, 9, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 1, 0, 0, 3, 0, 1, 0, 164, 1, 0, 0, 2, 0, 1, 0, 2, 0, 247, 255, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 1, 0, 0, 3, 0, 1, 0, 172, 1, 0, 0, 2, 0, 1, 0, 10, 0, 246, 255, 0, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 1, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 3, 0, 1, 0, 180, 1, 0, 0, 2, 0, 1, 0, 11, 0, 245, 255, 0, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 1, 0, 0, 3, 0, 1, 0, 184, 1, 0, 0, 2, 0, 1, 0, 12, 0, 244, 255, 0, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 1, 0, 0, 3, 0, 1, 0, 188, 1, 0, 0, 2, 0, 1, 0, 13, 0, 243, 255, 0, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 1, 0, 0, 3, 0, 1, 0, 192, 1, 0, 0, 2, 0, 1, 0, 8, 0, 242, 255, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 1, 0, 0, 3, 0, 1, 0, 200, 1, 0, 0, 2, 0, 1, 0, 117, 110, 105, 109, 112, 108, 101, 109, 101, 110, 116, 101, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 50, 176, 141, 128, 31, 159, 183, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98, 111, 114, 116, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 26, 105, 207, 58, 6, 183, 37, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 108, 108, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 212, 76, 157, 120, 206, 83, 106, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 116, 117, 114, 110, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 58, 87, 179, 61, 141, 178, 25, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 110, 105, 115, 104, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 99, 14, 248, 194, 178, 46, 125, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 111, 108, 118, 101, 0, 16, 0, 0, 0, 0, 0, 0, 0, 110, 8, 137, 250, 85, 150, 194, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 108, 101, 97, 115, 101, 0, 16, 0, 0, 0, 0, 0, 0, 0, 151, 116, 208, 125, 13, 108, 26, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 98, 115, 111, 108, 101, 116, 101, 83, 97, 118, 101, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 111, 111, 116, 115, 116, 114, 97, 112, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 196, 110, 23, 49, 128, 207, 76, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 98, 115, 111, 108, 101, 116, 101, 68, 101, 108, 101, 116, 101, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 114, 111, 118, 105, 100, 101, 0, 16, 0, 0, 0, 0, 0, 0, 0, 90, 172, 193, 251, 107, 4, 106, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 99, 99, 101, 112, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 22, 64, 85, 144, 98, 181, 201, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 111, 105, 110, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 175, 1, 224, 144, 4, 152, 225, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 101, 109, 98, 97, 114, 103, 111, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 17, 55, 189, 15, 139, 54, 100, 249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_91b79f1f808db032 = b_91b79f1f808db032.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_91b79f1f808db032[] = { &s_836a53ce789d4cd4, &s_91b79f1f808db032, &s_9c6a046bfbc1ac5a, &s_9e19b28d3db3573a, &s_ad1a6c0d7dd07497, &s_bbc29655fa89086e, &s_d37d2eb2c2f80e63, &s_d4c9b56290554016, &s_d625b7063acf691a, &s_e94ccf8031176ec4, &s_f964368b0fbd3711, &s_fbe1980490e001af, }; static const uint16_t m_91b79f1f808db032[] = {1, 11, 8, 2, 13, 4, 12, 9, 7, 10, 6, 5, 3, 0}; static const uint16_t i_91b79f1f808db032[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; const ::capnp::_::RawSchema s_91b79f1f808db032 = { 0x91b79f1f808db032, b_91b79f1f808db032.words, 232, d_91b79f1f808db032, m_91b79f1f808db032, 12, 14, i_91b79f1f808db032, nullptr, nullptr, { &s_91b79f1f808db032, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_e94ccf8031176ec4 = { { 0, 0, 0, 0, 5, 0, 6, 0, 196, 110, 23, 49, 128, 207, 76, 233, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 210, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 66, 111, 111, 116, 115, 116, 114, 97, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 3, 0, 1, 0, 64, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 101, 112, 114, 101, 99, 97, 116, 101, 100, 79, 98, 106, 101, 99, 116, 73, 100, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e94ccf8031176ec4 = b_e94ccf8031176ec4.words; #if !CAPNP_LITE static const uint16_t m_e94ccf8031176ec4[] = {1, 0}; static const uint16_t i_e94ccf8031176ec4[] = {0, 1}; const ::capnp::_::RawSchema s_e94ccf8031176ec4 = { 0xe94ccf8031176ec4, b_e94ccf8031176ec4.words, 51, nullptr, m_e94ccf8031176ec4, 0, 2, i_e94ccf8031176ec4, nullptr, nullptr, { &s_e94ccf8031176ec4, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<155> b_836a53ce789d4cd4 = { { 0, 0, 0, 0, 5, 0, 6, 0, 212, 76, 157, 120, 206, 83, 106, 131, 16, 0, 0, 0, 1, 0, 3, 0, 80, 162, 82, 37, 27, 152, 18, 179, 3, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 170, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 67, 97, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 36, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 3, 0, 1, 0, 248, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 3, 0, 1, 0, 252, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 0, 3, 0, 1, 0, 4, 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 1, 0, 12, 1, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 3, 0, 1, 0, 16, 1, 0, 0, 2, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 153, 95, 171, 26, 246, 176, 232, 218, 13, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 128, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 3, 0, 1, 0, 8, 1, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 129, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 3, 0, 1, 0, 20, 1, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 130, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 17, 1, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 0, 0, 3, 0, 1, 0, 32, 1, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 193, 251, 19, 88, 84, 20, 188, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 101, 114, 102, 97, 99, 101, 73, 100, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 101, 116, 104, 111, 100, 73, 100, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 115, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 59, 116, 150, 61, 34, 97, 14, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 101, 110, 100, 82, 101, 115, 117, 108, 116, 115, 84, 111, 0, 0, 0, 97, 108, 108, 111, 119, 84, 104, 105, 114, 100, 80, 97, 114, 116, 121, 84, 97, 105, 108, 67, 97, 108, 108, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 111, 80, 114, 111, 109, 105, 115, 101, 80, 105, 112, 101, 108, 105, 110, 105, 110, 103, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 110, 108, 121, 80, 114, 111, 109, 105, 115, 101, 80, 105, 112, 101, 108, 105, 110, 101, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_836a53ce789d4cd4 = b_836a53ce789d4cd4.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_836a53ce789d4cd4[] = { &s_95bc14545813fbc1, &s_9a0e61223d96743b, &s_dae8b0f61aab5f99, }; static const uint16_t m_836a53ce789d4cd4[] = {6, 2, 3, 7, 8, 4, 0, 5, 1}; static const uint16_t i_836a53ce789d4cd4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; const ::capnp::_::RawSchema s_836a53ce789d4cd4 = { 0x836a53ce789d4cd4, b_836a53ce789d4cd4.words, 155, d_836a53ce789d4cd4, m_836a53ce789d4cd4, 3, 9, i_836a53ce789d4cd4, nullptr, nullptr, { &s_836a53ce789d4cd4, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<65> b_dae8b0f61aab5f99 = { { 0, 0, 0, 0, 5, 0, 6, 0, 153, 95, 171, 26, 246, 176, 232, 218, 21, 0, 0, 0, 1, 0, 3, 0, 212, 76, 157, 120, 206, 83, 106, 131, 3, 0, 7, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 67, 97, 108, 108, 46, 115, 101, 110, 100, 82, 101, 115, 117, 108, 116, 115, 84, 111, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 2, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 92, 0, 0, 0, 2, 0, 1, 0, 99, 97, 108, 108, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 111, 117, 114, 115, 101, 108, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 104, 105, 114, 100, 80, 97, 114, 116, 121, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_dae8b0f61aab5f99 = b_dae8b0f61aab5f99.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_dae8b0f61aab5f99[] = { &s_836a53ce789d4cd4, }; static const uint16_t m_dae8b0f61aab5f99[] = {0, 2, 1}; static const uint16_t i_dae8b0f61aab5f99[] = {0, 1, 2}; const ::capnp::_::RawSchema s_dae8b0f61aab5f99 = { 0xdae8b0f61aab5f99, b_dae8b0f61aab5f99.words, 65, d_dae8b0f61aab5f99, m_dae8b0f61aab5f99, 1, 3, i_dae8b0f61aab5f99, nullptr, nullptr, { &s_dae8b0f61aab5f99, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<164> b_9e19b28d3db3573a = { { 0, 0, 0, 0, 5, 0, 6, 0, 58, 87, 179, 61, 141, 178, 25, 158, 16, 0, 0, 0, 1, 0, 2, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 82, 101, 116, 117, 114, 110, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 36, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 3, 0, 1, 0, 248, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 0, 3, 0, 1, 0, 4, 1, 0, 0, 2, 0, 1, 0, 3, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 3, 0, 1, 0, 8, 1, 0, 0, 2, 0, 1, 0, 4, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 3, 0, 1, 0, 16, 1, 0, 0, 2, 0, 1, 0, 5, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 1, 0, 0, 3, 0, 1, 0, 24, 1, 0, 0, 2, 0, 1, 0, 6, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 1, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 3, 0, 1, 0, 36, 1, 0, 0, 2, 0, 1, 0, 7, 0, 251, 255, 2, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 1, 0, 0, 3, 0, 1, 0, 48, 1, 0, 0, 2, 0, 1, 0, 8, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 1, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 3, 0, 1, 0, 60, 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 33, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 57, 1, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 1, 0, 0, 3, 0, 1, 0, 68, 1, 0, 0, 2, 0, 1, 0, 97, 110, 115, 119, 101, 114, 73, 100, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 108, 101, 97, 115, 101, 80, 97, 114, 97, 109, 67, 97, 112, 115, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 117, 108, 116, 115, 0, 16, 0, 0, 0, 0, 0, 0, 0, 59, 116, 150, 61, 34, 97, 14, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 26, 105, 207, 58, 6, 183, 37, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 110, 99, 101, 108, 101, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 117, 108, 116, 115, 83, 101, 110, 116, 69, 108, 115, 101, 119, 104, 101, 114, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 107, 101, 70, 114, 111, 109, 79, 116, 104, 101, 114, 81, 117, 101, 115, 116, 105, 111, 110, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 99, 99, 101, 112, 116, 70, 114, 111, 109, 84, 104, 105, 114, 100, 80, 97, 114, 116, 121, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 111, 70, 105, 110, 105, 115, 104, 78, 101, 101, 100, 101, 100, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9e19b28d3db3573a = b_9e19b28d3db3573a.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9e19b28d3db3573a[] = { &s_9a0e61223d96743b, &s_d625b7063acf691a, }; static const uint16_t m_9e19b28d3db3573a[] = {7, 0, 4, 3, 8, 1, 2, 5, 6}; static const uint16_t i_9e19b28d3db3573a[] = {2, 3, 4, 5, 6, 7, 0, 1, 8}; const ::capnp::_::RawSchema s_9e19b28d3db3573a = { 0x9e19b28d3db3573a, b_9e19b28d3db3573a.words, 164, d_9e19b28d3db3573a, m_9e19b28d3db3573a, 2, 9, i_9e19b28d3db3573a, nullptr, nullptr, { &s_9e19b28d3db3573a, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<69> b_d37d2eb2c2f80e63 = { { 0, 0, 0, 0, 5, 0, 6, 0, 99, 14, 248, 194, 178, 46, 125, 211, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 70, 105, 110, 105, 115, 104, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 92, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 33, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 3, 0, 1, 0, 112, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 108, 101, 97, 115, 101, 82, 101, 115, 117, 108, 116, 67, 97, 112, 115, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 113, 117, 105, 114, 101, 69, 97, 114, 108, 121, 67, 97, 110, 99, 101, 108, 108, 97, 116, 105, 111, 110, 87, 111, 114, 107, 97, 114, 111, 117, 110, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d37d2eb2c2f80e63 = b_d37d2eb2c2f80e63.words; #if !CAPNP_LITE static const uint16_t m_d37d2eb2c2f80e63[] = {0, 1, 2}; static const uint16_t i_d37d2eb2c2f80e63[] = {0, 1, 2}; const ::capnp::_::RawSchema s_d37d2eb2c2f80e63 = { 0xd37d2eb2c2f80e63, b_d37d2eb2c2f80e63.words, 69, nullptr, m_d37d2eb2c2f80e63, 0, 3, i_d37d2eb2c2f80e63, nullptr, nullptr, { &s_d37d2eb2c2f80e63, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<64> b_bbc29655fa89086e = { { 0, 0, 0, 0, 5, 0, 6, 0, 110, 8, 137, 250, 85, 150, 194, 187, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 82, 101, 115, 111, 108, 118, 101, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 92, 0, 0, 0, 2, 0, 1, 0, 112, 114, 111, 109, 105, 115, 101, 73, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 176, 184, 134, 11, 196, 221, 35, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 26, 105, 207, 58, 6, 183, 37, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_bbc29655fa89086e = b_bbc29655fa89086e.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_bbc29655fa89086e[] = { &s_8523ddc40b86b8b0, &s_d625b7063acf691a, }; static const uint16_t m_bbc29655fa89086e[] = {1, 2, 0}; static const uint16_t i_bbc29655fa89086e[] = {1, 2, 0}; const ::capnp::_::RawSchema s_bbc29655fa89086e = { 0xbbc29655fa89086e, b_bbc29655fa89086e.words, 64, d_bbc29655fa89086e, m_bbc29655fa89086e, 2, 3, i_bbc29655fa89086e, nullptr, nullptr, { &s_bbc29655fa89086e, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<48> b_ad1a6c0d7dd07497 = { { 0, 0, 0, 0, 5, 0, 6, 0, 151, 116, 208, 125, 13, 108, 26, 173, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 82, 101, 108, 101, 97, 115, 101, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 102, 101, 114, 101, 110, 99, 101, 67, 111, 117, 110, 116, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ad1a6c0d7dd07497 = b_ad1a6c0d7dd07497.words; #if !CAPNP_LITE static const uint16_t m_ad1a6c0d7dd07497[] = {0, 1}; static const uint16_t i_ad1a6c0d7dd07497[] = {0, 1}; const ::capnp::_::RawSchema s_ad1a6c0d7dd07497 = { 0xad1a6c0d7dd07497, b_ad1a6c0d7dd07497.words, 48, nullptr, m_ad1a6c0d7dd07497, 0, 2, i_ad1a6c0d7dd07497, nullptr, nullptr, { &s_ad1a6c0d7dd07497, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<41> b_f964368b0fbd3711 = { { 0, 0, 0, 0, 5, 0, 6, 0, 17, 55, 189, 15, 139, 54, 100, 249, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 218, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 68, 105, 115, 101, 109, 98, 97, 114, 103, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 77, 221, 91, 101, 223, 180, 98, 213, 45, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 193, 251, 19, 88, 84, 20, 188, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 111, 110, 116, 101, 120, 116, 0, } }; ::capnp::word const* const bp_f964368b0fbd3711 = b_f964368b0fbd3711.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_f964368b0fbd3711[] = { &s_95bc14545813fbc1, &s_d562b4df655bdd4d, }; static const uint16_t m_f964368b0fbd3711[] = {1, 0}; static const uint16_t i_f964368b0fbd3711[] = {0, 1}; const ::capnp::_::RawSchema s_f964368b0fbd3711 = { 0xf964368b0fbd3711, b_f964368b0fbd3711.words, 41, d_f964368b0fbd3711, m_f964368b0fbd3711, 2, 2, i_f964368b0fbd3711, nullptr, nullptr, { &s_f964368b0fbd3711, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<81> b_d562b4df655bdd4d = { { 0, 0, 0, 0, 5, 0, 6, 0, 77, 221, 91, 101, 223, 180, 98, 213, 27, 0, 0, 0, 1, 0, 1, 0, 17, 55, 189, 15, 139, 54, 100, 249, 1, 0, 7, 0, 1, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 26, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 68, 105, 115, 101, 109, 98, 97, 114, 103, 111, 46, 99, 111, 110, 116, 101, 120, 116, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 3, 0, 1, 0, 108, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 3, 0, 1, 0, 120, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 3, 0, 1, 0, 124, 0, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 3, 0, 1, 0, 128, 0, 0, 0, 2, 0, 1, 0, 115, 101, 110, 100, 101, 114, 76, 111, 111, 112, 98, 97, 99, 107, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 99, 101, 105, 118, 101, 114, 76, 111, 111, 112, 98, 97, 99, 107, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 99, 99, 101, 112, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 114, 111, 118, 105, 100, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d562b4df655bdd4d = b_d562b4df655bdd4d.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d562b4df655bdd4d[] = { &s_f964368b0fbd3711, }; static const uint16_t m_d562b4df655bdd4d[] = {2, 3, 1, 0}; static const uint16_t i_d562b4df655bdd4d[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_d562b4df655bdd4d = { 0xd562b4df655bdd4d, b_d562b4df655bdd4d.words, 81, d_d562b4df655bdd4d, m_d562b4df655bdd4d, 1, 4, i_d562b4df655bdd4d, nullptr, nullptr, { &s_d562b4df655bdd4d, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<64> b_9c6a046bfbc1ac5a = { { 0, 0, 0, 0, 5, 0, 6, 0, 90, 172, 193, 251, 107, 4, 106, 156, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 80, 114, 111, 118, 105, 100, 101, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 92, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 193, 251, 19, 88, 84, 20, 188, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 99, 105, 112, 105, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9c6a046bfbc1ac5a = b_9c6a046bfbc1ac5a.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9c6a046bfbc1ac5a[] = { &s_95bc14545813fbc1, }; static const uint16_t m_9c6a046bfbc1ac5a[] = {0, 2, 1}; static const uint16_t i_9c6a046bfbc1ac5a[] = {0, 1, 2}; const ::capnp::_::RawSchema s_9c6a046bfbc1ac5a = { 0x9c6a046bfbc1ac5a, b_9c6a046bfbc1ac5a.words, 64, d_9c6a046bfbc1ac5a, m_9c6a046bfbc1ac5a, 1, 3, i_9c6a046bfbc1ac5a, nullptr, nullptr, { &s_9c6a046bfbc1ac5a, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<64> b_d4c9b56290554016 = { { 0, 0, 0, 0, 5, 0, 6, 0, 22, 64, 85, 144, 98, 181, 201, 212, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 65, 99, 99, 101, 112, 116, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 32, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 92, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 114, 111, 118, 105, 115, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 109, 98, 97, 114, 103, 111, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d4c9b56290554016 = b_d4c9b56290554016.words; #if !CAPNP_LITE static const uint16_t m_d4c9b56290554016[] = {2, 1, 0}; static const uint16_t i_d4c9b56290554016[] = {0, 1, 2}; const ::capnp::_::RawSchema s_d4c9b56290554016 = { 0xd4c9b56290554016, b_d4c9b56290554016.words, 64, nullptr, m_d4c9b56290554016, 0, 3, i_d4c9b56290554016, nullptr, nullptr, { &s_d4c9b56290554016, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<63> b_fbe1980490e001af = { { 0, 0, 0, 0, 5, 0, 6, 0, 175, 1, 224, 144, 4, 152, 225, 251, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 170, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 74, 111, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 193, 251, 19, 88, 84, 20, 188, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 101, 121, 80, 97, 114, 116, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_fbe1980490e001af = b_fbe1980490e001af.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_fbe1980490e001af[] = { &s_95bc14545813fbc1, }; static const uint16_t m_fbe1980490e001af[] = {2, 0, 1}; static const uint16_t i_fbe1980490e001af[] = {0, 1, 2}; const ::capnp::_::RawSchema s_fbe1980490e001af = { 0xfbe1980490e001af, b_fbe1980490e001af.words, 63, d_fbe1980490e001af, m_fbe1980490e001af, 1, 3, i_fbe1980490e001af, nullptr, nullptr, { &s_fbe1980490e001af, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<50> b_95bc14545813fbc1 = { { 0, 0, 0, 0, 5, 0, 6, 0, 193, 251, 19, 88, 84, 20, 188, 149, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 242, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 77, 101, 115, 115, 97, 103, 101, 84, 97, 114, 103, 101, 116, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 3, 0, 1, 0, 60, 0, 0, 0, 2, 0, 1, 0, 105, 109, 112, 111, 114, 116, 101, 100, 67, 97, 112, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 114, 111, 109, 105, 115, 101, 100, 65, 110, 115, 119, 101, 114, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 160, 28, 111, 205, 214, 177, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_95bc14545813fbc1 = b_95bc14545813fbc1.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_95bc14545813fbc1[] = { &s_d800b1d6cd6f1ca0, }; static const uint16_t m_95bc14545813fbc1[] = {0, 1}; static const uint16_t i_95bc14545813fbc1[] = {0, 1}; const ::capnp::_::RawSchema s_95bc14545813fbc1 = { 0x95bc14545813fbc1, b_95bc14545813fbc1.words, 50, d_95bc14545813fbc1, m_95bc14545813fbc1, 1, 2, i_95bc14545813fbc1, nullptr, nullptr, { &s_95bc14545813fbc1, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<52> b_9a0e61223d96743b = { { 0, 0, 0, 0, 5, 0, 6, 0, 59, 116, 150, 61, 34, 97, 14, 154, 16, 0, 0, 0, 1, 0, 0, 0, 80, 162, 82, 37, 27, 152, 18, 179, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 80, 97, 121, 108, 111, 97, 100, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 72, 0, 0, 0, 2, 0, 1, 0, 99, 111, 110, 116, 101, 110, 116, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 84, 97, 98, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 176, 184, 134, 11, 196, 221, 35, 133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9a0e61223d96743b = b_9a0e61223d96743b.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9a0e61223d96743b[] = { &s_8523ddc40b86b8b0, }; static const uint16_t m_9a0e61223d96743b[] = {1, 0}; static const uint16_t i_9a0e61223d96743b[] = {0, 1}; const ::capnp::_::RawSchema s_9a0e61223d96743b = { 0x9a0e61223d96743b, b_9a0e61223d96743b.words, 52, d_9a0e61223d96743b, m_9a0e61223d96743b, 1, 2, i_9a0e61223d96743b, nullptr, nullptr, { &s_9a0e61223d96743b, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<130> b_8523ddc40b86b8b0 = { { 0, 0, 0, 0, 5, 0, 6, 0, 176, 184, 134, 11, 196, 221, 35, 133, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 242, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 143, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 67, 97, 112, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 28, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, 0, 0, 3, 0, 1, 0, 188, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 3, 0, 1, 0, 196, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 3, 0, 1, 0, 204, 0, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 3, 0, 1, 0, 212, 0, 0, 0, 2, 0, 1, 0, 4, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 3, 0, 1, 0, 220, 0, 0, 0, 2, 0, 1, 0, 5, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 3, 0, 1, 0, 232, 0, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 3, 0, 1, 0, 240, 0, 0, 0, 2, 0, 1, 0, 110, 111, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 101, 110, 100, 101, 114, 72, 111, 115, 116, 101, 100, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 101, 110, 100, 101, 114, 80, 114, 111, 109, 105, 115, 101, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 99, 101, 105, 118, 101, 114, 72, 111, 115, 116, 101, 100, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 99, 101, 105, 118, 101, 114, 65, 110, 115, 119, 101, 114, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 160, 28, 111, 205, 214, 177, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 104, 105, 114, 100, 80, 97, 114, 116, 121, 72, 111, 115, 116, 101, 100, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 125, 2, 240, 225, 253, 7, 112, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 116, 116, 97, 99, 104, 101, 100, 70, 100, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_8523ddc40b86b8b0 = b_8523ddc40b86b8b0.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_8523ddc40b86b8b0[] = { &s_d37007fde1f0027d, &s_d800b1d6cd6f1ca0, }; static const uint16_t m_8523ddc40b86b8b0[] = {6, 0, 4, 3, 1, 2, 5}; static const uint16_t i_8523ddc40b86b8b0[] = {0, 1, 2, 3, 4, 5, 6}; const ::capnp::_::RawSchema s_8523ddc40b86b8b0 = { 0x8523ddc40b86b8b0, b_8523ddc40b86b8b0.words, 130, d_8523ddc40b86b8b0, m_8523ddc40b86b8b0, 2, 7, i_8523ddc40b86b8b0, nullptr, nullptr, { &s_8523ddc40b86b8b0, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<57> b_d800b1d6cd6f1ca0 = { { 0, 0, 0, 0, 5, 0, 6, 0, 160, 28, 111, 205, 214, 177, 0, 216, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 80, 114, 111, 109, 105, 115, 101, 100, 65, 110, 115, 119, 101, 114, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 129, 144, 86, 21, 68, 148, 22, 243, 1, 0, 0, 0, 26, 0, 0, 0, 79, 112, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 113, 117, 101, 115, 116, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 114, 97, 110, 115, 102, 111, 114, 109, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 129, 144, 86, 21, 68, 148, 22, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d800b1d6cd6f1ca0 = b_d800b1d6cd6f1ca0.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d800b1d6cd6f1ca0[] = { &s_f316944415569081, }; static const uint16_t m_d800b1d6cd6f1ca0[] = {0, 1}; static const uint16_t i_d800b1d6cd6f1ca0[] = {0, 1}; const ::capnp::_::RawSchema s_d800b1d6cd6f1ca0 = { 0xd800b1d6cd6f1ca0, b_d800b1d6cd6f1ca0.words, 57, d_d800b1d6cd6f1ca0, m_d800b1d6cd6f1ca0, 1, 2, i_d800b1d6cd6f1ca0, nullptr, nullptr, { &s_d800b1d6cd6f1ca0, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<50> b_f316944415569081 = { { 0, 0, 0, 0, 5, 0, 6, 0, 129, 144, 86, 21, 68, 148, 22, 243, 31, 0, 0, 0, 1, 0, 1, 0, 160, 28, 111, 205, 214, 177, 0, 216, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 80, 114, 111, 109, 105, 115, 101, 100, 65, 110, 115, 119, 101, 114, 46, 79, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 110, 111, 111, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 101, 116, 80, 111, 105, 110, 116, 101, 114, 70, 105, 101, 108, 100, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f316944415569081 = b_f316944415569081.words; #if !CAPNP_LITE static const uint16_t m_f316944415569081[] = {1, 0}; static const uint16_t i_f316944415569081[] = {0, 1}; const ::capnp::_::RawSchema s_f316944415569081 = { 0xf316944415569081, b_f316944415569081.words, 50, nullptr, m_f316944415569081, 0, 2, i_f316944415569081, nullptr, nullptr, { &s_f316944415569081, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_d37007fde1f0027d = { { 0, 0, 0, 0, 5, 0, 6, 0, 125, 2, 240, 225, 253, 7, 112, 211, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 66, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 84, 104, 105, 114, 100, 80, 97, 114, 116, 121, 67, 97, 112, 68, 101, 115, 99, 114, 105, 112, 116, 111, 114, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 105, 110, 101, 73, 100, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d37007fde1f0027d = b_d37007fde1f0027d.words; #if !CAPNP_LITE static const uint16_t m_d37007fde1f0027d[] = {0, 1}; static const uint16_t i_d37007fde1f0027d[] = {0, 1}; const ::capnp::_::RawSchema s_d37007fde1f0027d = { 0xd37007fde1f0027d, b_d37007fde1f0027d.words, 49, nullptr, m_d37007fde1f0027d, 0, 2, i_d37007fde1f0027d, nullptr, nullptr, { &s_d37007fde1f0027d, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<100> b_d625b7063acf691a = { { 0, 0, 0, 0, 5, 0, 6, 0, 26, 105, 207, 58, 6, 183, 37, 214, 16, 0, 0, 0, 1, 0, 1, 0, 80, 162, 82, 37, 27, 152, 18, 179, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 210, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 69, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 88, 189, 76, 63, 226, 150, 140, 178, 1, 0, 0, 0, 42, 0, 0, 0, 84, 121, 112, 101, 0, 0, 0, 0, 20, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 3, 0, 1, 0, 132, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 3, 0, 1, 0, 144, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 3, 0, 1, 0, 156, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 3, 0, 1, 0, 160, 0, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 3, 0, 1, 0, 164, 0, 0, 0, 2, 0, 1, 0, 114, 101, 97, 115, 111, 110, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 98, 115, 111, 108, 101, 116, 101, 73, 115, 67, 97, 108, 108, 101, 114, 115, 70, 97, 117, 108, 116, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 98, 115, 111, 108, 101, 116, 101, 68, 117, 114, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 88, 189, 76, 63, 226, 150, 140, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 114, 97, 99, 101, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d625b7063acf691a = b_d625b7063acf691a.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d625b7063acf691a[] = { &s_b28c96e23f4cbd58, }; static const uint16_t m_d625b7063acf691a[] = {2, 1, 0, 4, 3}; static const uint16_t i_d625b7063acf691a[] = {0, 1, 2, 3, 4}; const ::capnp::_::RawSchema s_d625b7063acf691a = { 0xd625b7063acf691a, b_d625b7063acf691a.words, 100, d_d625b7063acf691a, m_d625b7063acf691a, 1, 5, i_d625b7063acf691a, nullptr, nullptr, { &s_d625b7063acf691a, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<37> b_b28c96e23f4cbd58 = { { 0, 0, 0, 0, 5, 0, 6, 0, 88, 189, 76, 63, 226, 150, 140, 178, 26, 0, 0, 0, 2, 0, 0, 0, 26, 105, 207, 58, 6, 183, 37, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 46, 99, 97, 112, 110, 112, 58, 69, 120, 99, 101, 112, 116, 105, 111, 110, 46, 84, 121, 112, 101, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 16, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 97, 105, 108, 101, 100, 0, 0, 111, 118, 101, 114, 108, 111, 97, 100, 101, 100, 0, 0, 0, 0, 0, 0, 100, 105, 115, 99, 111, 110, 110, 101, 99, 116, 101, 100, 0, 0, 0, 0, 117, 110, 105, 109, 112, 108, 101, 109, 101, 110, 116, 101, 100, 0, 0, 0, } }; ::capnp::word const* const bp_b28c96e23f4cbd58 = b_b28c96e23f4cbd58.words; #if !CAPNP_LITE static const uint16_t m_b28c96e23f4cbd58[] = {2, 0, 1, 3}; const ::capnp::_::RawSchema s_b28c96e23f4cbd58 = { 0xb28c96e23f4cbd58, b_b28c96e23f4cbd58.words, 37, nullptr, m_b28c96e23f4cbd58, 0, 4, nullptr, nullptr, nullptr, { &s_b28c96e23f4cbd58, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE CAPNP_DEFINE_ENUM(Type_b28c96e23f4cbd58, b28c96e23f4cbd58); } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace rpc { // Message #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Message::_capnpPrivate::dataWordSize; constexpr uint16_t Message::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Message::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Message::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Bootstrap #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Bootstrap::_capnpPrivate::dataWordSize; constexpr uint16_t Bootstrap::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Bootstrap::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Bootstrap::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Call #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Call::_capnpPrivate::dataWordSize; constexpr uint16_t Call::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Call::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Call::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Call::SendResultsTo #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Call::SendResultsTo::_capnpPrivate::dataWordSize; constexpr uint16_t Call::SendResultsTo::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Call::SendResultsTo::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Call::SendResultsTo::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Return #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Return::_capnpPrivate::dataWordSize; constexpr uint16_t Return::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Return::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Return::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Finish #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Finish::_capnpPrivate::dataWordSize; constexpr uint16_t Finish::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Finish::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Finish::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Resolve #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Resolve::_capnpPrivate::dataWordSize; constexpr uint16_t Resolve::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Resolve::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Resolve::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Release #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Release::_capnpPrivate::dataWordSize; constexpr uint16_t Release::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Release::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Release::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Disembargo #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Disembargo::_capnpPrivate::dataWordSize; constexpr uint16_t Disembargo::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Disembargo::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Disembargo::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Disembargo::Context #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Disembargo::Context::_capnpPrivate::dataWordSize; constexpr uint16_t Disembargo::Context::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Disembargo::Context::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Disembargo::Context::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Provide #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Provide::_capnpPrivate::dataWordSize; constexpr uint16_t Provide::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Provide::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Provide::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Accept #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Accept::_capnpPrivate::dataWordSize; constexpr uint16_t Accept::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Accept::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Accept::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Join #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Join::_capnpPrivate::dataWordSize; constexpr uint16_t Join::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Join::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Join::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // MessageTarget #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t MessageTarget::_capnpPrivate::dataWordSize; constexpr uint16_t MessageTarget::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind MessageTarget::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* MessageTarget::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Payload #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Payload::_capnpPrivate::dataWordSize; constexpr uint16_t Payload::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Payload::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Payload::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CapDescriptor #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CapDescriptor::_capnpPrivate::dataWordSize; constexpr uint16_t CapDescriptor::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CapDescriptor::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CapDescriptor::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // PromisedAnswer #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t PromisedAnswer::_capnpPrivate::dataWordSize; constexpr uint16_t PromisedAnswer::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind PromisedAnswer::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* PromisedAnswer::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // PromisedAnswer::Op #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t PromisedAnswer::Op::_capnpPrivate::dataWordSize; constexpr uint16_t PromisedAnswer::Op::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind PromisedAnswer::Op::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* PromisedAnswer::Op::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // ThirdPartyCapDescriptor #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t ThirdPartyCapDescriptor::_capnpPrivate::dataWordSize; constexpr uint16_t ThirdPartyCapDescriptor::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind ThirdPartyCapDescriptor::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* ThirdPartyCapDescriptor::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Exception #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Exception::_capnpPrivate::dataWordSize; constexpr uint16_t Exception::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Exception::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Exception::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/any.h0000644000175000017500000010757414712011043017601 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "layout.h" #include "pointer-helpers.h" #include "orphan.h" #include "list.h" #include // work-around macro conflict with `VOID` #include CAPNP_BEGIN_HEADER namespace capnp { class StructSchema; class ListSchema; class InterfaceSchema; class Orphanage; class ClientHook; class PipelineHook; struct PipelineOp; struct AnyPointer; struct AnyList { AnyList() = delete; class Reader; class Builder; }; struct AnyStruct { AnyStruct() = delete; class Reader; class Builder; class Pipeline; }; template<> struct List { List() = delete; class Reader; class Builder; }; namespace _ { // private template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; } // namespace _ (private) // ======================================================================================= // AnyPointer! enum class Equality { NOT_EQUAL, EQUAL, UNKNOWN_CONTAINS_CAPS }; kj::StringPtr KJ_STRINGIFY(Equality res); struct AnyPointer { // Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary // object. AnyPointer() = delete; class Reader { public: typedef AnyPointer Reads; Reader() = default; inline Reader(_::PointerReader reader): reader(reader) {} inline MessageSize targetSize() const; // Get the total size of the target object and all its children. inline PointerType getPointerType() const; inline bool isNull() const { return getPointerType() == PointerType::NULL_; } inline bool isStruct() const { return getPointerType() == PointerType::STRUCT; } inline bool isList() const { return getPointerType() == PointerType::LIST; } inline bool isCapability() const { return getPointerType() == PointerType::CAPABILITY; } Equality equals(AnyPointer::Reader right) const; bool operator==(AnyPointer::Reader right) const; inline bool operator!=(AnyPointer::Reader right) const { return !(*this == right); } template inline ReaderFor getAs() const; // Valid for T = any generated struct type, interface type, List, Text, or Data. template inline ReaderFor getAs(StructSchema schema) const; // Only valid for T = DynamicStruct. Requires `#include `. template inline ReaderFor getAs(ListSchema schema) const; // Only valid for T = DynamicList. Requires `#include `. template inline ReaderFor getAs(InterfaceSchema schema) const; // Only valid for T = DynamicCapability. Requires `#include `. #if !CAPNP_LITE kj::Own getPipelinedCap(kj::ArrayPtr ops) const; // Used by RPC system to implement pipelining. Applications generally shouldn't use this // directly. #endif // !CAPNP_LITE private: _::PointerReader reader; friend struct AnyPointer; friend class Orphanage; friend class CapReaderContext; friend struct _::PointerHelpers; }; class Builder { public: typedef AnyPointer Builds; Builder() = delete; inline Builder(decltype(nullptr)) {} inline Builder(_::PointerBuilder builder): builder(builder) {} inline MessageSize targetSize() const; // Get the total size of the target object and all its children. inline PointerType getPointerType(); inline bool isNull() { return getPointerType() == PointerType::NULL_; } inline bool isStruct() { return getPointerType() == PointerType::STRUCT; } inline bool isList() { return getPointerType() == PointerType::LIST; } inline bool isCapability() { return getPointerType() == PointerType::CAPABILITY; } inline Equality equals(AnyPointer::Reader right) const { return asReader().equals(right); } inline bool operator==(AnyPointer::Reader right) const { return asReader() == right; } inline bool operator!=(AnyPointer::Reader right) const { return !(*this == right); } inline void clear(); // Set to null. template inline BuilderFor getAs(); // Valid for T = any generated struct type, List, Text, or Data. template inline BuilderFor getAs(StructSchema schema); // Only valid for T = DynamicStruct. Requires `#include `. template inline BuilderFor getAs(ListSchema schema); // Only valid for T = DynamicList. Requires `#include `. template inline BuilderFor getAs(InterfaceSchema schema); // Only valid for T = DynamicCapability. Requires `#include `. template inline BuilderFor initAs(); // Valid for T = any generated struct type. template inline BuilderFor initAs(uint elementCount); // Valid for T = List, Text, or Data. template inline BuilderFor initAs(StructSchema schema); // Only valid for T = DynamicStruct. Requires `#include `. template inline BuilderFor initAs(ListSchema schema, uint elementCount); // Only valid for T = DynamicList. Requires `#include `. inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount); // Note: Does not accept INLINE_COMPOSITE for elementSize. inline List::Builder initAsListOfAnyStruct( uint16_t dataWordCount, uint16_t pointerCount, uint elementCount); inline AnyStruct::Builder initAsAnyStruct(uint16_t dataWordCount, uint16_t pointerCount); template inline void setAs(ReaderFor value); // Valid for ReaderType = T::Reader for T = any generated struct type, List, Text, Data, // DynamicStruct, or DynamicList (the dynamic types require `#include `). template inline void setAs(std::initializer_list>> list); // Valid for T = List. template inline void setCanonicalAs(ReaderFor value); inline void set(Reader value) { builder.copyFrom(value.reader); } // Set to a copy of another AnyPointer. inline void setCanonical(Reader value) { builder.copyFrom(value.reader, true); } template inline void adopt(Orphan&& orphan); // Valid for T = any generated struct type, List, Text, Data, DynamicList, DynamicStruct, // or DynamicValue (the dynamic types require `#include `). template inline Orphan disownAs(); // Valid for T = any generated struct type, List, Text, Data. template inline Orphan disownAs(StructSchema schema); // Only valid for T = DynamicStruct. Requires `#include `. template inline Orphan disownAs(ListSchema schema); // Only valid for T = DynamicList. Requires `#include `. template inline Orphan disownAs(InterfaceSchema schema); // Only valid for T = DynamicCapability. Requires `#include `. inline Orphan disown(); // Disown without a type. inline Reader asReader() const { return Reader(builder.asReader()); } inline operator Reader() const { return Reader(builder.asReader()); } private: _::PointerBuilder builder; friend class Orphanage; friend class CapBuilderContext; friend struct _::PointerHelpers; }; #if !CAPNP_LITE class Pipeline { public: typedef AnyPointer Pipelines; inline Pipeline(decltype(nullptr)) {} inline explicit Pipeline(kj::Own&& hook): hook(kj::mv(hook)) {} Pipeline noop(); // Just make a copy. Pipeline getPointerField(uint16_t pointerIndex); // Deprecated. In the future, we should use .asAnyStruct.getPointerField. inline AnyStruct::Pipeline asAnyStruct(); kj::Own asCap(); // Expect that the result is a capability and construct a pipelined version of it now. inline kj::Own releasePipelineHook() { return kj::mv(hook); } // For use by RPC implementations. template ) == Kind::INTERFACE>> inline operator T() { return T(asCap()); } private: kj::Own hook; kj::Array ops; inline Pipeline(kj::Own&& hook, kj::Array&& ops) : hook(kj::mv(hook)), ops(kj::mv(ops)) {} friend class LocalClient; friend class PipelineHook; friend class AnyStruct::Pipeline; }; #endif // !CAPNP_LITE }; template <> class Orphan { // An orphaned object of unknown type. public: Orphan() = default; KJ_DISALLOW_COPY(Orphan); Orphan(Orphan&&) = default; inline Orphan(_::OrphanBuilder&& builder) : builder(kj::mv(builder)) {} Orphan& operator=(Orphan&&) = default; template inline Orphan(Orphan&& other): builder(kj::mv(other.builder)) {} template inline Orphan& operator=(Orphan&& other) { builder = kj::mv(other.builder); return *this; } // Cast from typed orphan. // It's not possible to get an AnyPointer::{Reader,Builder} directly since there is no // underlying pointer (the pointer would normally live in the parent, but this object is // orphaned). It is possible, however, to request typed readers/builders. template inline BuilderFor getAs(); template inline BuilderFor getAs(StructSchema schema); template inline BuilderFor getAs(ListSchema schema); template inline typename T::Client getAs(InterfaceSchema schema); template inline ReaderFor getAsReader() const; template inline ReaderFor getAsReader(StructSchema schema) const; template inline ReaderFor getAsReader(ListSchema schema) const; template inline typename T::Client getAsReader(InterfaceSchema schema) const; template inline Orphan releaseAs(); template inline Orphan releaseAs(StructSchema schema); template inline Orphan releaseAs(ListSchema schema); template inline Orphan releaseAs(InterfaceSchema schema); // Down-cast the orphan to a specific type. inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } private: _::OrphanBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend class Orphan; friend class AnyPointer::Builder; }; template struct AnyTypeFor_; template <> struct AnyTypeFor_ { typedef AnyStruct Type; }; template <> struct AnyTypeFor_ { typedef AnyList Type; }; template using AnyTypeFor = typename AnyTypeFor_::Type; template inline ReaderFor>> toAny(T&& value) { return ReaderFor>>( _::PointerHelpers>::getInternalReader(value)); } template inline BuilderFor>> toAny(T&& value) { return BuilderFor>>( _::PointerHelpers>::getInternalBuilder(kj::mv(value))); } template <> struct List { // Note: This cannot be used for a list of structs, since such lists are not encoded as pointer // lists! Use List. List() = delete; class Reader { public: typedef List Reads; inline Reader(): reader(ElementSize::POINTER) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline AnyPointer::Reader operator[](uint index) const { KJ_IREQUIRE(index < size()); return AnyPointer::Reader(reader.getPointerElement(bounded(index) * ELEMENTS)); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List Builds; Builder() = delete; inline Builder(decltype(nullptr)): builder(ElementSize::POINTER) {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline AnyPointer::Builder operator[](uint index) { KJ_IREQUIRE(index < size()); return AnyPointer::Builder(builder.getPointerElement(bounded(index) * ELEMENTS)); } typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; }; class AnyStruct::Reader { public: typedef AnyStruct Reads; Reader() = default; inline Reader(_::StructReader reader): _reader(reader) {} template ) == Kind::STRUCT>> inline Reader(T&& value) : _reader(_::PointerHelpers>::getInternalReader(kj::fwd(value))) {} inline MessageSize totalSize() const { return _reader.totalSize().asPublic(); } kj::ArrayPtr getDataSection() const { return _reader.getDataSectionAsBlob(); } List::Reader getPointerSection() const { return List::Reader(_reader.getPointerSectionAsList()); } kj::Array canonicalize() { return _reader.canonicalize(); } Equality equals(AnyStruct::Reader right) const; bool operator==(AnyStruct::Reader right) const; inline bool operator!=(AnyStruct::Reader right) const { return !(*this == right); } template ReaderFor as() const { // T must be a struct type. return typename T::Reader(_reader); } template ReaderFor as(StructSchema schema) const; // T must be DynamicStruct. Defined in dynamic.h. private: _::StructReader _reader; template friend struct _::PointerHelpers; friend class Orphanage; }; class AnyStruct::Builder { public: typedef AnyStruct Builds; inline Builder(decltype(nullptr)) {} inline Builder(_::StructBuilder builder): _builder(builder) {} #if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. template ) == Kind::STRUCT>> inline Builder(T&& value) : _builder(_::PointerHelpers>::getInternalBuilder(kj::fwd(value))) {} #endif inline kj::ArrayPtr getDataSection() { return _builder.getDataSectionAsBlob(); } List::Builder getPointerSection() { return List::Builder(_builder.getPointerSectionAsList()); } inline Equality equals(AnyStruct::Reader right) const { return asReader().equals(right); } inline bool operator==(AnyStruct::Reader right) const { return asReader() == right; } inline bool operator!=(AnyStruct::Reader right) const { return !(*this == right); } inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return Reader(_builder.asReader()); } template BuilderFor as() { // T must be a struct type. return typename T::Builder(_builder); } template BuilderFor as(StructSchema schema); // T must be DynamicStruct. Defined in dynamic.h. private: _::StructBuilder _builder; friend class Orphanage; friend class CapBuilderContext; }; #if !CAPNP_LITE class AnyStruct::Pipeline { public: inline Pipeline(decltype(nullptr)): typeless(nullptr) {} inline explicit Pipeline(AnyPointer::Pipeline&& typeless) : typeless(kj::mv(typeless)) {} inline AnyPointer::Pipeline getPointerField(uint16_t pointerIndex) { // Return a new Promise representing a sub-object of the result. `pointerIndex` is the index // of the sub-object within the pointer section of the result (the result must be a struct). // // TODO(perf): On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies. // Also make `ops` into a Vector to optimize this. return typeless.getPointerField(pointerIndex); } private: AnyPointer::Pipeline typeless; }; #endif // !CAPNP_LITE class List::Reader { public: typedef List Reads; inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {} inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline AnyStruct::Reader operator[](uint index) const { KJ_IREQUIRE(index < size()); return AnyStruct::Reader(reader.getStructElement(bounded(index) * ELEMENTS)); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class List::Builder { public: typedef List Builds; Builder() = delete; inline Builder(decltype(nullptr)): builder(ElementSize::INLINE_COMPOSITE) {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline AnyStruct::Builder operator[](uint index) { KJ_IREQUIRE(index < size()); return AnyStruct::Builder(builder.getStructElement(bounded(index) * ELEMENTS)); } typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; template friend struct _::PointerHelpers; friend class Orphanage; template friend struct ToDynamic_; }; class AnyList::Reader { public: typedef AnyList Reads; inline Reader(): _reader(ElementSize::VOID) {} inline Reader(_::ListReader reader): _reader(reader) {} #if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. template ) == Kind::LIST>> inline Reader(T&& value) : _reader(_::PointerHelpers>::getInternalReader(kj::fwd(value))) {} #endif inline ElementSize getElementSize() const { return _reader.getElementSize(); } inline uint size() const { return unbound(_reader.size() / ELEMENTS); } inline kj::ArrayPtr getRawBytes() const { return _reader.asRawBytes(); } Equality equals(AnyList::Reader right) const; bool operator==(AnyList::Reader right) const; inline bool operator!=(AnyList::Reader right) const { return !(*this == right); } inline MessageSize totalSize() const { return _reader.totalSize().asPublic(); } template ReaderFor as() const { // T must be List. return ReaderFor(_reader); } private: _::ListReader _reader; template friend struct _::PointerHelpers; friend class Orphanage; }; class AnyList::Builder { public: typedef AnyList Builds; inline Builder(decltype(nullptr)): _builder(ElementSize::VOID) {} inline Builder(_::ListBuilder builder): _builder(builder) {} #if !_MSC_VER || defined(__clang__) // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves. template ) == Kind::LIST>> inline Builder(T&& value) : _builder(_::PointerHelpers>::getInternalBuilder(kj::fwd(value))) {} #endif inline ElementSize getElementSize() { return _builder.getElementSize(); } inline uint size() { return unbound(_builder.size() / ELEMENTS); } Equality equals(AnyList::Reader right) const; inline bool operator==(AnyList::Reader right) const{ return asReader() == right; } inline bool operator!=(AnyList::Reader right) const{ return !(*this == right); } template BuilderFor as() { // T must be List. return BuilderFor(_builder); } inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return Reader(_builder.asReader()); } private: _::ListBuilder _builder; friend class Orphanage; }; // ======================================================================================= // Pipeline helpers // // These relate to capabilities, but we don't declare them in capability.h because generated code // for structs needs to know about these, even in files that contain no interfaces. #if !CAPNP_LITE struct PipelineOp { // Corresponds to rpc.capnp's PromisedAnswer.Op. enum Type { NOOP, // for convenience GET_POINTER_FIELD // There may be other types in the future... }; Type type; union { uint16_t pointerIndex; // for GET_POINTER_FIELD }; }; inline uint KJ_HASHCODE(const PipelineOp& op) { switch (op.type) { case PipelineOp::NOOP: return kj::hashCode(op.type); case PipelineOp::GET_POINTER_FIELD: return kj::hashCode(op.type, op.pointerIndex); } KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT } inline bool operator==(const PipelineOp& a, const PipelineOp& b) { if (a.type != b.type) return false; switch (a.type) { case PipelineOp::NOOP: return true; case PipelineOp::GET_POINTER_FIELD: return a.pointerIndex == b.pointerIndex; } KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT } inline bool operator!=(const PipelineOp& a, const PipelineOp& b) { return !(a == b); } class PipelineHook { // Represents a currently-running call, and implements pipelined requests on its result. public: virtual kj::Own addRef() = 0; // Increment this object's reference count. virtual kj::Own getPipelinedCap(kj::ArrayPtr ops) = 0; // Extract a promised Capability from the results. virtual kj::Own getPipelinedCap(kj::Array&& ops); // Version of getPipelinedCap() passing the array by move. May avoid a copy in some cases. // Default implementation just calls the other version. template > static inline kj::Own from(Pipeline&& pipeline); template > static inline PipelineHook& from(Pipeline& pipeline); private: template struct FromImpl; }; #endif // !CAPNP_LITE // ======================================================================================= // Inline implementation details inline MessageSize AnyPointer::Reader::targetSize() const { return reader.targetSize().asPublic(); } inline PointerType AnyPointer::Reader::getPointerType() const { return reader.getPointerType(); } template inline ReaderFor AnyPointer::Reader::getAs() const { return _::PointerHelpers::get(reader); } inline MessageSize AnyPointer::Builder::targetSize() const { return asReader().targetSize(); } inline PointerType AnyPointer::Builder::getPointerType() { return builder.getPointerType(); } inline void AnyPointer::Builder::clear() { return builder.clear(); } template inline BuilderFor AnyPointer::Builder::getAs() { return _::PointerHelpers::get(builder); } template inline BuilderFor AnyPointer::Builder::initAs() { return _::PointerHelpers::init(builder); } template inline BuilderFor AnyPointer::Builder::initAs(uint elementCount) { return _::PointerHelpers::init(builder, elementCount); } inline AnyList::Builder AnyPointer::Builder::initAsAnyList( ElementSize elementSize, uint elementCount) { return AnyList::Builder(builder.initList(elementSize, bounded(elementCount) * ELEMENTS)); } inline List::Builder AnyPointer::Builder::initAsListOfAnyStruct( uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) { return List::Builder(builder.initStructList(bounded(elementCount) * ELEMENTS, _::StructSize(bounded(dataWordCount) * WORDS, bounded(pointerCount) * POINTERS))); } inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct( uint16_t dataWordCount, uint16_t pointerCount) { return AnyStruct::Builder(builder.initStruct( _::StructSize(bounded(dataWordCount) * WORDS, bounded(pointerCount) * POINTERS))); } template inline void AnyPointer::Builder::setAs(ReaderFor value) { return _::PointerHelpers::set(builder, value); } template inline void AnyPointer::Builder::setCanonicalAs(ReaderFor value) { return _::PointerHelpers::setCanonical(builder, value); } template inline void AnyPointer::Builder::setAs( std::initializer_list>> list) { return _::PointerHelpers::set(builder, list); } template inline void AnyPointer::Builder::adopt(Orphan&& orphan) { _::PointerHelpers::adopt(builder, kj::mv(orphan)); } template inline Orphan AnyPointer::Builder::disownAs() { return _::PointerHelpers::disown(builder); } inline Orphan AnyPointer::Builder::disown() { return Orphan(builder.disown()); } template <> struct ReaderFor_ { typedef AnyPointer::Reader Type; }; template <> struct BuilderFor_ { typedef AnyPointer::Builder Type; }; template <> struct ReaderFor_ { typedef AnyStruct::Reader Type; }; template <> struct BuilderFor_ { typedef AnyStruct::Builder Type; }; template <> struct Orphanage::GetInnerReader { static inline _::PointerReader apply(const AnyPointer::Reader& t) { return t.reader; } }; template <> struct Orphanage::GetInnerBuilder { static inline _::PointerBuilder apply(AnyPointer::Builder& t) { return t.builder; } }; template <> struct Orphanage::GetInnerReader { static inline _::StructReader apply(const AnyStruct::Reader& t) { return t._reader; } }; template <> struct Orphanage::GetInnerBuilder { static inline _::StructBuilder apply(AnyStruct::Builder& t) { return t._builder; } }; template <> struct Orphanage::GetInnerReader { static inline _::ListReader apply(const AnyList::Reader& t) { return t._reader; } }; template <> struct Orphanage::GetInnerBuilder { static inline _::ListBuilder apply(AnyList::Builder& t) { return t._builder; } }; template inline BuilderFor Orphan::getAs() { return _::OrphanGetImpl::apply(builder); } template inline ReaderFor Orphan::getAsReader() const { return _::OrphanGetImpl::applyReader(builder); } template inline Orphan Orphan::releaseAs() { return Orphan(kj::mv(builder)); } // Using AnyPointer as the template type should work... template <> inline typename AnyPointer::Reader AnyPointer::Reader::getAs() const { return *this; } template <> inline typename AnyPointer::Builder AnyPointer::Builder::getAs() { return *this; } template <> inline typename AnyPointer::Builder AnyPointer::Builder::initAs() { clear(); return *this; } template <> inline void AnyPointer::Builder::setAs(AnyPointer::Reader value) { return builder.copyFrom(value.reader); } template <> inline void AnyPointer::Builder::adopt(Orphan&& orphan) { builder.adopt(kj::mv(orphan.builder)); } template <> inline Orphan AnyPointer::Builder::disownAs() { return Orphan(builder.disown()); } template <> inline Orphan Orphan::releaseAs() { return kj::mv(*this); } namespace _ { // private // Specialize PointerHelpers for AnyPointer. template <> struct PointerHelpers { static inline AnyPointer::Reader get(PointerReader reader, const void* defaultValue = nullptr, uint defaultBytes = 0) { return AnyPointer::Reader(reader); } static inline AnyPointer::Builder get(PointerBuilder builder, const void* defaultValue = nullptr, uint defaultBytes = 0) { return AnyPointer::Builder(builder); } static inline void set(PointerBuilder builder, AnyPointer::Reader value) { AnyPointer::Builder(builder).set(value); } static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } static inline _::PointerReader getInternalReader(const AnyPointer::Reader& reader) { return reader.reader; } static inline _::PointerBuilder getInternalBuilder(AnyPointer::Builder&& builder) { return builder.builder; } }; template <> struct PointerHelpers { static inline AnyStruct::Reader get( PointerReader reader, const word* defaultValue = nullptr) { return AnyStruct::Reader(reader.getStruct(defaultValue)); } static inline AnyStruct::Builder get( PointerBuilder builder, const word* defaultValue = nullptr) { // TODO(someday): Allow specifying the size somehow? return AnyStruct::Builder(builder.getStruct( _::StructSize(ZERO * WORDS, ZERO * POINTERS), defaultValue)); } static inline void set(PointerBuilder builder, AnyStruct::Reader value) { builder.setStruct(value._reader); } static inline AnyStruct::Builder init( PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount) { return AnyStruct::Builder(builder.initStruct( StructSize(bounded(dataWordCount) * WORDS, bounded(pointerCount) * POINTERS))); } static void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } }; template <> struct PointerHelpers { static inline AnyList::Reader get( PointerReader reader, const word* defaultValue = nullptr) { return AnyList::Reader(reader.getListAnySize(defaultValue)); } static inline AnyList::Builder get( PointerBuilder builder, const word* defaultValue = nullptr) { return AnyList::Builder(builder.getListAnySize(defaultValue)); } static inline void set(PointerBuilder builder, AnyList::Reader value) { builder.setList(value._reader); } static inline AnyList::Builder init( PointerBuilder builder, ElementSize elementSize, uint elementCount) { return AnyList::Builder(builder.initList( elementSize, bounded(elementCount) * ELEMENTS)); } static inline AnyList::Builder init( PointerBuilder builder, uint16_t dataWordCount, uint16_t pointerCount, uint elementCount) { return AnyList::Builder(builder.initStructList( bounded(elementCount) * ELEMENTS, StructSize(bounded(dataWordCount) * WORDS, bounded(pointerCount) * POINTERS))); } static void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } }; template <> struct OrphanGetImpl { static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) { return AnyStruct::Builder(builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); } static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) { return AnyStruct::Reader(builder.asStructReader(_::StructSize(ZERO * WORDS, ZERO * POINTERS))); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, _::StructSize(ZERO * WORDS, ZERO * POINTERS)); } }; template <> struct OrphanGetImpl { static inline AnyList::Builder apply(_::OrphanBuilder& builder) { return AnyList::Builder(builder.asListAnySize()); } static inline AnyList::Reader applyReader(const _::OrphanBuilder& builder) { return AnyList::Reader(builder.asListReaderAnySize()); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; } // namespace _ (private) #if !CAPNP_LITE template struct PipelineHook::FromImpl { static inline kj::Own apply(typename T::Pipeline&& pipeline) { return from(kj::mv(pipeline._typeless)); } static inline PipelineHook& apply(typename T::Pipeline& pipeline) { return from(pipeline._typeless); } }; template <> struct PipelineHook::FromImpl { static inline kj::Own apply(AnyPointer::Pipeline&& pipeline) { return kj::mv(pipeline.hook); } static inline PipelineHook& apply(AnyPointer::Pipeline& pipeline) { return *pipeline.hook; } }; template inline kj::Own PipelineHook::from(Pipeline&& pipeline) { return FromImpl::apply(kj::fwd(pipeline)); } template inline PipelineHook& PipelineHook::from(Pipeline& pipeline) { return FromImpl::apply(pipeline); } #endif // !CAPNP_LITE } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/schema-lite.h0000644000175000017500000000356314527152321021207 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include "message.h" CAPNP_BEGIN_HEADER namespace capnp { template inline schema::Node::Reader schemaProto() { // Get the schema::Node for this type's schema. This function works even in lite mode. return readMessageUnchecked(CapnpPrivate::encodedSchema()); } template ::typeId> inline schema::Node::Reader schemaProto() { // Get the schema::Node for this type's schema. This function works even in lite mode. return readMessageUnchecked(schemas::EnumInfo::encodedSchema()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/0000755000175000017500000000000014731562205020451 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/capnp/compiler/lexer.capnp.c++0000644000175000017500000005322314712011043023153 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: lexer.capnp #include "lexer.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<195> b_91cc55cd57de5419 = { { 0, 0, 0, 0, 5, 0, 6, 0, 25, 84, 222, 87, 205, 85, 204, 145, 27, 0, 0, 0, 1, 0, 3, 0, 238, 195, 31, 98, 210, 86, 57, 167, 1, 0, 7, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 55, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 108, 101, 120, 101, 114, 46, 99, 97, 112, 110, 112, 58, 84, 111, 107, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 40, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 3, 0, 1, 0, 20, 1, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, 0, 3, 0, 1, 0, 28, 1, 0, 0, 2, 0, 1, 0, 3, 0, 253, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 3, 0, 1, 0, 36, 1, 0, 0, 2, 0, 1, 0, 4, 0, 252, 255, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, 3, 0, 1, 0, 44, 1, 0, 0, 2, 0, 1, 0, 5, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 1, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 1, 0, 0, 3, 0, 1, 0, 52, 1, 0, 0, 2, 0, 1, 0, 6, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 1, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 1, 0, 0, 3, 0, 1, 0, 96, 1, 0, 0, 2, 0, 1, 0, 7, 0, 249, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 1, 0, 0, 3, 0, 1, 0, 136, 1, 0, 0, 2, 0, 1, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 1, 0, 0, 3, 0, 1, 0, 144, 1, 0, 0, 2, 0, 1, 0, 9, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 1, 0, 0, 3, 0, 1, 0, 148, 1, 0, 0, 2, 0, 1, 0, 2, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 3, 0, 1, 0, 156, 1, 0, 0, 2, 0, 1, 0, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 105, 110, 103, 76, 105, 116, 101, 114, 97, 108, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 101, 103, 101, 114, 76, 105, 116, 101, 114, 97, 108, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 76, 105, 116, 101, 114, 97, 108, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, 101, 114, 97, 116, 111, 114, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 101, 110, 116, 104, 101, 115, 105, 122, 101, 100, 76, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 25, 84, 222, 87, 205, 85, 204, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 99, 107, 101, 116, 101, 100, 76, 105, 115, 116, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 25, 84, 222, 87, 205, 85, 204, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 105, 110, 97, 114, 121, 76, 105, 116, 101, 114, 97, 108, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_91cc55cd57de5419 = b_91cc55cd57de5419.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_91cc55cd57de5419[] = { &s_91cc55cd57de5419, }; static const uint16_t m_91cc55cd57de5419[] = {9, 6, 8, 3, 0, 2, 4, 5, 7, 1}; static const uint16_t i_91cc55cd57de5419[] = {0, 1, 2, 3, 4, 5, 6, 9, 7, 8}; const ::capnp::_::RawSchema s_91cc55cd57de5419 = { 0x91cc55cd57de5419, b_91cc55cd57de5419.words, 195, d_91cc55cd57de5419, m_91cc55cd57de5419, 1, 10, i_91cc55cd57de5419, nullptr, nullptr, { &s_91cc55cd57de5419, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<119> b_c6725e678d60fa37 = { { 0, 0, 0, 0, 5, 0, 6, 0, 55, 250, 96, 141, 103, 94, 114, 198, 27, 0, 0, 0, 1, 0, 2, 0, 238, 195, 31, 98, 210, 86, 57, 167, 3, 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 87, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 108, 101, 120, 101, 114, 46, 99, 97, 112, 110, 112, 58, 83, 116, 97, 116, 101, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 3, 0, 1, 0, 176, 0, 0, 0, 2, 0, 1, 0, 1, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 3, 0, 1, 0, 180, 0, 0, 0, 2, 0, 1, 0, 2, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 3, 0, 1, 0, 200, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, 0, 0, 3, 0, 1, 0, 208, 0, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 3, 0, 1, 0, 216, 0, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 3, 0, 1, 0, 220, 0, 0, 0, 2, 0, 1, 0, 116, 111, 107, 101, 110, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 25, 84, 222, 87, 205, 85, 204, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 105, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 108, 111, 99, 107, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 55, 250, 96, 141, 103, 94, 114, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 111, 99, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c6725e678d60fa37 = b_c6725e678d60fa37.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c6725e678d60fa37[] = { &s_91cc55cd57de5419, &s_c6725e678d60fa37, }; static const uint16_t m_c6725e678d60fa37[] = {2, 3, 5, 1, 4, 0}; static const uint16_t i_c6725e678d60fa37[] = {1, 2, 0, 3, 4, 5}; const ::capnp::_::RawSchema s_c6725e678d60fa37 = { 0xc6725e678d60fa37, b_c6725e678d60fa37.words, 119, d_c6725e678d60fa37, m_c6725e678d60fa37, 2, 6, i_c6725e678d60fa37, nullptr, nullptr, { &s_c6725e678d60fa37, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<38> b_9e69a92512b19d18 = { { 0, 0, 0, 0, 5, 0, 6, 0, 24, 157, 177, 18, 37, 169, 105, 158, 27, 0, 0, 0, 1, 0, 0, 0, 238, 195, 31, 98, 210, 86, 57, 167, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 58, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 108, 101, 120, 101, 114, 46, 99, 97, 112, 110, 112, 58, 76, 101, 120, 101, 100, 84, 111, 107, 101, 110, 115, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 36, 0, 0, 0, 2, 0, 1, 0, 116, 111, 107, 101, 110, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 25, 84, 222, 87, 205, 85, 204, 145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9e69a92512b19d18 = b_9e69a92512b19d18.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9e69a92512b19d18[] = { &s_91cc55cd57de5419, }; static const uint16_t m_9e69a92512b19d18[] = {0}; static const uint16_t i_9e69a92512b19d18[] = {0}; const ::capnp::_::RawSchema s_9e69a92512b19d18 = { 0x9e69a92512b19d18, b_9e69a92512b19d18.words, 38, d_9e69a92512b19d18, m_9e69a92512b19d18, 1, 1, i_9e69a92512b19d18, nullptr, nullptr, { &s_9e69a92512b19d18, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<40> b_a11f97b9d6c73dd4 = { { 0, 0, 0, 0, 5, 0, 6, 0, 212, 61, 199, 214, 185, 151, 31, 161, 27, 0, 0, 0, 1, 0, 0, 0, 238, 195, 31, 98, 210, 86, 57, 167, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 90, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 108, 101, 120, 101, 114, 46, 99, 97, 112, 110, 112, 58, 76, 101, 120, 101, 100, 83, 116, 97, 116, 101, 109, 101, 110, 116, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 40, 0, 0, 0, 2, 0, 1, 0, 115, 116, 97, 116, 101, 109, 101, 110, 116, 115, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 55, 250, 96, 141, 103, 94, 114, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_a11f97b9d6c73dd4 = b_a11f97b9d6c73dd4.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_a11f97b9d6c73dd4[] = { &s_c6725e678d60fa37, }; static const uint16_t m_a11f97b9d6c73dd4[] = {0}; static const uint16_t i_a11f97b9d6c73dd4[] = {0}; const ::capnp::_::RawSchema s_a11f97b9d6c73dd4 = { 0xa11f97b9d6c73dd4, b_a11f97b9d6c73dd4.words, 40, d_a11f97b9d6c73dd4, m_a11f97b9d6c73dd4, 1, 1, i_a11f97b9d6c73dd4, nullptr, nullptr, { &s_a11f97b9d6c73dd4, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace compiler { // Token #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Token::_capnpPrivate::dataWordSize; constexpr uint16_t Token::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Token::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Token::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Statement #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Statement::_capnpPrivate::dataWordSize; constexpr uint16_t Statement::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Statement::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Statement::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // LexedTokens #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t LexedTokens::_capnpPrivate::dataWordSize; constexpr uint16_t LexedTokens::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind LexedTokens::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* LexedTokens::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // LexedStatements #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t LexedStatements::_capnpPrivate::dataWordSize; constexpr uint16_t LexedStatements::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind LexedStatements::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* LexedStatements::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/compiler/generics.c++0000644000175000017500000005742314731420004022543 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2020 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "generics.h" #include "parser.h" // for expressionString() namespace capnp { namespace compiler { BrandedDecl::BrandedDecl(BrandedDecl& other) : body(other.body), source(other.source) { if (body.is()) { brand = kj::addRef(*other.brand); } } BrandedDecl& BrandedDecl::operator=(BrandedDecl& other) { body = other.body; source = other.source; if (body.is()) { brand = kj::addRef(*other.brand); } return *this; } kj::Maybe BrandedDecl::applyParams( kj::Array params, Expression::Reader subSource) { if (body.is()) { return nullptr; } else { return brand->setParams(kj::mv(params), body.get().kind, subSource) .map([&](kj::Own&& scope) { BrandedDecl result = *this; result.brand = kj::mv(scope); result.source = subSource; return result; }); } } kj::Maybe BrandedDecl::getMember( kj::StringPtr memberName, Expression::Reader subSource) { if (body.is()) { return nullptr; } else KJ_IF_MAYBE(r, body.get().resolver->resolveMember(memberName)) { return brand->interpretResolve(*body.get().resolver, *r, subSource); } else { return nullptr; } } kj::Maybe BrandedDecl::getKind() { if (body.is()) { return nullptr; } else { return body.get().kind; } } kj::Maybe BrandedDecl::getListParam() { KJ_REQUIRE(body.is()); auto& decl = body.get(); KJ_REQUIRE(decl.kind == Declaration::BUILTIN_LIST); auto params = KJ_ASSERT_NONNULL(brand->getParams(decl.id)); if (params.size() != 1) { return nullptr; } else { return params[0]; } } Resolver::ResolvedParameter BrandedDecl::asVariable() { KJ_REQUIRE(body.is()); return body.get(); } bool BrandedDecl::compileAsType( ErrorReporter& errorReporter, schema::Type::Builder target) { KJ_IF_MAYBE(kind, getKind()) { switch (*kind) { case Declaration::ENUM: { auto enum_ = target.initEnum(); enum_.setTypeId(getIdAndFillBrand([&]() { return enum_.initBrand(); })); return true; } case Declaration::STRUCT: { auto struct_ = target.initStruct(); struct_.setTypeId(getIdAndFillBrand([&]() { return struct_.initBrand(); })); return true; } case Declaration::INTERFACE: { auto interface = target.initInterface(); interface.setTypeId(getIdAndFillBrand([&]() { return interface.initBrand(); })); return true; } case Declaration::BUILTIN_LIST: { auto elementType = target.initList().initElementType(); KJ_IF_MAYBE(param, getListParam()) { if (!param->compileAsType(errorReporter, elementType)) { return false; } } else { addError(errorReporter, "'List' requires exactly one parameter."); return false; } if (elementType.isAnyPointer()) { auto unconstrained = elementType.getAnyPointer().getUnconstrained(); if (unconstrained.isAnyKind()) { addError(errorReporter, "'List(AnyPointer)' is not supported."); // Seeing List(AnyPointer) later can mess things up, so change the type to Void. elementType.setVoid(); return false; } else if (unconstrained.isStruct()) { addError(errorReporter, "'List(AnyStruct)' is not supported."); // Seeing List(AnyStruct) later can mess things up, so change the type to Void. elementType.setVoid(); return false; } } return true; } case Declaration::BUILTIN_VOID: target.setVoid(); return true; case Declaration::BUILTIN_BOOL: target.setBool(); return true; case Declaration::BUILTIN_INT8: target.setInt8(); return true; case Declaration::BUILTIN_INT16: target.setInt16(); return true; case Declaration::BUILTIN_INT32: target.setInt32(); return true; case Declaration::BUILTIN_INT64: target.setInt64(); return true; case Declaration::BUILTIN_U_INT8: target.setUint8(); return true; case Declaration::BUILTIN_U_INT16: target.setUint16(); return true; case Declaration::BUILTIN_U_INT32: target.setUint32(); return true; case Declaration::BUILTIN_U_INT64: target.setUint64(); return true; case Declaration::BUILTIN_FLOAT32: target.setFloat32(); return true; case Declaration::BUILTIN_FLOAT64: target.setFloat64(); return true; case Declaration::BUILTIN_TEXT: target.setText(); return true; case Declaration::BUILTIN_DATA: target.setData(); return true; case Declaration::BUILTIN_OBJECT: addError(errorReporter, "As of Cap'n Proto 0.4, 'Object' has been renamed to 'AnyPointer'. Sorry for the " "inconvenience, and thanks for being an early adopter. :)"); KJ_FALLTHROUGH; case Declaration::BUILTIN_ANY_POINTER: target.initAnyPointer().initUnconstrained().setAnyKind(); return true; case Declaration::BUILTIN_ANY_STRUCT: target.initAnyPointer().initUnconstrained().setStruct(); return true; case Declaration::BUILTIN_ANY_LIST: target.initAnyPointer().initUnconstrained().setList(); return true; case Declaration::BUILTIN_CAPABILITY: target.initAnyPointer().initUnconstrained().setCapability(); return true; case Declaration::FILE: case Declaration::USING: case Declaration::CONST: case Declaration::ENUMERANT: case Declaration::FIELD: case Declaration::UNION: case Declaration::GROUP: case Declaration::METHOD: case Declaration::ANNOTATION: case Declaration::NAKED_ID: case Declaration::NAKED_ANNOTATION: addError(errorReporter, kj::str("'", toString(), "' is not a type.")); return false; } KJ_UNREACHABLE; } else { // Oh, this is a type variable. auto var = asVariable(); if (var.id == 0) { // This is actually a method implicit parameter. auto builder = target.initAnyPointer().initImplicitMethodParameter(); builder.setParameterIndex(var.index); return true; } else { auto builder = target.initAnyPointer().initParameter(); builder.setScopeId(var.id); builder.setParameterIndex(var.index); return true; } } } Resolver::ResolveResult BrandedDecl::asResolveResult( uint64_t scopeId, schema::Brand::Builder brandBuilder) { auto result = body; if (result.is()) { // May need to compile our context as the "brand". result.get().scopeId = scopeId; getIdAndFillBrand([&]() { result.get().brand = brandBuilder.asReader(); return brandBuilder; }); } return result; } kj::String BrandedDecl::toString() { return expressionString(source); } kj::String BrandedDecl::toDebugString() { if (body.is()) { auto variable = body.get(); return kj::str("variable(", variable.id, ", ", variable.index, ")"); } else { auto decl = body.get(); return kj::str("decl(", decl.id, ", ", (uint)decl.kind, "')"); } } BrandScope::BrandScope(ErrorReporter& errorReporter, uint64_t startingScopeId, uint startingScopeParamCount, Resolver& startingScope) : errorReporter(errorReporter), parent(nullptr), leafId(startingScopeId), leafParamCount(startingScopeParamCount), inherited(true) { // Create all lexical parent scopes, all with no brand bindings. KJ_IF_MAYBE(p, startingScope.getParent()) { parent = kj::refcounted( errorReporter, p->id, p->genericParamCount, *p->resolver); } } bool BrandScope::isGeneric() { if (leafParamCount > 0) return true; KJ_IF_MAYBE(p, parent) { return p->get()->isGeneric(); } else { return false; } } kj::Own BrandScope::push(uint64_t typeId, uint paramCount) { return kj::refcounted(kj::addRef(*this), typeId, paramCount); } kj::Maybe> BrandScope::setParams( kj::Array params, Declaration::Which genericType, Expression::Reader source) { if (this->params.size() != 0) { errorReporter.addErrorOn(source, "Double-application of generic parameters."); return nullptr; } else if (params.size() > leafParamCount) { if (leafParamCount == 0) { errorReporter.addErrorOn(source, "Declaration does not accept generic parameters."); } else { errorReporter.addErrorOn(source, "Too many generic parameters."); } return nullptr; } else if (params.size() < leafParamCount) { errorReporter.addErrorOn(source, "Not enough generic parameters."); return nullptr; } else { if (genericType != Declaration::BUILTIN_LIST) { for (auto& param: params) { KJ_IF_MAYBE(kind, param.getKind()) { switch (*kind) { case Declaration::BUILTIN_LIST: case Declaration::BUILTIN_TEXT: case Declaration::BUILTIN_DATA: case Declaration::BUILTIN_ANY_POINTER: case Declaration::STRUCT: case Declaration::INTERFACE: break; default: param.addError(errorReporter, "Sorry, only pointer types can be used as generic parameters."); break; } } } } return kj::refcounted(*this, kj::mv(params)); } } kj::Own BrandScope::pop(uint64_t newLeafId) { if (leafId == newLeafId) { return kj::addRef(*this); } KJ_IF_MAYBE(p, parent) { return (*p)->pop(newLeafId); } else { // Looks like we're moving into a whole top-level scope. return kj::refcounted(errorReporter, newLeafId); } } kj::Maybe BrandScope::lookupParameter( Resolver& resolver, uint64_t scopeId, uint index) { // Returns null if the param should be inherited from the client scope. if (scopeId == leafId) { if (index < params.size()) { return params[index]; } else if (inherited) { return nullptr; } else { // Unbound and not inherited, so return AnyPointer. auto decl = resolver.resolveBuiltin(Declaration::BUILTIN_ANY_POINTER); return BrandedDecl(decl, evaluateBrand(resolver, decl, List::Reader()), Expression::Reader()); } } else KJ_IF_MAYBE(p, parent) { return p->get()->lookupParameter(resolver, scopeId, index); } else { KJ_FAIL_REQUIRE("scope is not a parent"); } } kj::Maybe> BrandScope::getParams(uint64_t scopeId) { // Returns null if params at the requested scope should be inherited from the client scope. if (scopeId == leafId) { if (inherited) { return nullptr; } else { return params.asPtr(); } } else KJ_IF_MAYBE(p, parent) { return p->get()->getParams(scopeId); } else { KJ_FAIL_REQUIRE("scope is not a parent"); } } BrandedDecl BrandScope::interpretResolve( Resolver& resolver, Resolver::ResolveResult& result, Expression::Reader source) { if (result.is()) { auto& decl = result.get(); auto scope = pop(decl.scopeId); KJ_IF_MAYBE(brand, decl.brand) { scope = scope->evaluateBrand(resolver, decl, brand->getScopes()); } else { scope = scope->push(decl.id, decl.genericParamCount); } return BrandedDecl(decl, kj::mv(scope), source); } else { auto& param = result.get(); KJ_IF_MAYBE(p, lookupParameter(resolver, param.id, param.index)) { return *p; } else { return BrandedDecl(param, source); } } } kj::Own BrandScope::evaluateBrand( Resolver& resolver, Resolver::ResolvedDecl decl, List::Reader brand, uint index) { auto result = kj::refcounted(errorReporter, decl.id); result->leafParamCount = decl.genericParamCount; // Fill in `params`. if (index < brand.size()) { auto nextScope = brand[index]; if (decl.id == nextScope.getScopeId()) { // Initialize our parameters. switch (nextScope.which()) { case schema::Brand::Scope::BIND: { auto bindings = nextScope.getBind(); auto params = kj::heapArrayBuilder(bindings.size()); for (auto binding: bindings) { switch (binding.which()) { case schema::Brand::Binding::UNBOUND: { // Build an AnyPointer-equivalent. auto anyPointerDecl = resolver.resolveBuiltin(Declaration::BUILTIN_ANY_POINTER); params.add(BrandedDecl(anyPointerDecl, kj::refcounted(errorReporter, anyPointerDecl.scopeId), Expression::Reader())); break; } case schema::Brand::Binding::TYPE: // Reverse this schema::Type back into a BrandedDecl. params.add(decompileType(resolver, binding.getType())); break; } } result->params = params.finish(); break; } case schema::Brand::Scope::INHERIT: KJ_IF_MAYBE(p, getParams(decl.id)) { result->params = kj::heapArray(*p); } else { result->inherited = true; } break; } // Parent should start one level deeper in the list. ++index; } } // Fill in `parent`. KJ_IF_MAYBE(parent, decl.resolver->getParent()) { result->parent = evaluateBrand(resolver, *parent, brand, index); } return result; } BrandedDecl BrandScope::decompileType( Resolver& resolver, schema::Type::Reader type) { auto builtin = [&](Declaration::Which which) -> BrandedDecl { auto decl = resolver.resolveBuiltin(which); return BrandedDecl(decl, evaluateBrand(resolver, decl, List::Reader()), Expression::Reader()); }; switch (type.which()) { case schema::Type::VOID: return builtin(Declaration::BUILTIN_VOID); case schema::Type::BOOL: return builtin(Declaration::BUILTIN_BOOL); case schema::Type::INT8: return builtin(Declaration::BUILTIN_INT8); case schema::Type::INT16: return builtin(Declaration::BUILTIN_INT16); case schema::Type::INT32: return builtin(Declaration::BUILTIN_INT32); case schema::Type::INT64: return builtin(Declaration::BUILTIN_INT64); case schema::Type::UINT8: return builtin(Declaration::BUILTIN_U_INT8); case schema::Type::UINT16: return builtin(Declaration::BUILTIN_U_INT16); case schema::Type::UINT32: return builtin(Declaration::BUILTIN_U_INT32); case schema::Type::UINT64: return builtin(Declaration::BUILTIN_U_INT64); case schema::Type::FLOAT32: return builtin(Declaration::BUILTIN_FLOAT32); case schema::Type::FLOAT64: return builtin(Declaration::BUILTIN_FLOAT64); case schema::Type::TEXT: return builtin(Declaration::BUILTIN_TEXT); case schema::Type::DATA: return builtin(Declaration::BUILTIN_DATA); case schema::Type::ENUM: { auto enumType = type.getEnum(); Resolver::ResolvedDecl decl = resolver.resolveId(enumType.getTypeId()); return BrandedDecl(decl, evaluateBrand(resolver, decl, enumType.getBrand().getScopes()), Expression::Reader()); } case schema::Type::INTERFACE: { auto interfaceType = type.getInterface(); Resolver::ResolvedDecl decl = resolver.resolveId(interfaceType.getTypeId()); return BrandedDecl(decl, evaluateBrand(resolver, decl, interfaceType.getBrand().getScopes()), Expression::Reader()); } case schema::Type::STRUCT: { auto structType = type.getStruct(); Resolver::ResolvedDecl decl = resolver.resolveId(structType.getTypeId()); return BrandedDecl(decl, evaluateBrand(resolver, decl, structType.getBrand().getScopes()), Expression::Reader()); } case schema::Type::LIST: { auto elementType = decompileType(resolver, type.getList().getElementType()); return KJ_ASSERT_NONNULL(builtin(Declaration::BUILTIN_LIST) .applyParams(kj::heapArray(&elementType, 1), Expression::Reader())); } case schema::Type::ANY_POINTER: { auto anyPointer = type.getAnyPointer(); switch (anyPointer.which()) { case schema::Type::AnyPointer::UNCONSTRAINED: return builtin(Declaration::BUILTIN_ANY_POINTER); case schema::Type::AnyPointer::PARAMETER: { auto param = anyPointer.getParameter(); auto id = param.getScopeId(); uint index = param.getParameterIndex(); KJ_IF_MAYBE(binding, lookupParameter(resolver, id, index)) { return *binding; } else { return BrandedDecl(Resolver::ResolvedParameter {id, index}, Expression::Reader()); } } case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: KJ_FAIL_ASSERT("Alias pointed to implicit method type parameter?"); } KJ_UNREACHABLE; } } KJ_UNREACHABLE; } kj::Maybe BrandScope::compileDeclExpression( Expression::Reader source, Resolver& resolver, ImplicitParams implicitMethodParams) { switch (source.which()) { case Expression::UNKNOWN: // Error reported earlier. return nullptr; case Expression::POSITIVE_INT: case Expression::NEGATIVE_INT: case Expression::FLOAT: case Expression::STRING: case Expression::BINARY: case Expression::LIST: case Expression::TUPLE: case Expression::EMBED: errorReporter.addErrorOn(source, "Expected name."); return nullptr; case Expression::RELATIVE_NAME: { auto name = source.getRelativeName(); auto nameValue = name.getValue(); // Check implicit method params first. for (auto i: kj::indices(implicitMethodParams.params)) { if (implicitMethodParams.params[i].getName() == nameValue) { if (implicitMethodParams.scopeId == 0) { return BrandedDecl::implicitMethodParam(i); } else { return BrandedDecl(Resolver::ResolvedParameter { implicitMethodParams.scopeId, static_cast(i) }, Expression::Reader()); } } } KJ_IF_MAYBE(r, resolver.resolve(nameValue)) { auto result = interpretResolve(resolver, *r, source); if (r->is()){ errorReporter.reportResolution(Resolution { /* .startByte = */ source.getStartByte(), /* .endByte = */ source.getEndByte(), /* .target = */ Resolution::Type { r->get().id }, }); } return kj::mv(result); } else { errorReporter.addErrorOn(name, kj::str("Not defined: ", nameValue)); return nullptr; } } case Expression::ABSOLUTE_NAME: { auto name = source.getAbsoluteName(); KJ_IF_MAYBE(r, resolver.getTopScope().resolver->resolveMember(name.getValue())) { auto result = interpretResolve(resolver, *r, source); if (r->is()){ errorReporter.reportResolution(Resolution { /* .startByte = */ source.getStartByte(), /* .endByte = */ source.getEndByte(), /* .target = */ Resolution::Type { r->get().id }, }); } return kj::mv(result); } else { errorReporter.addErrorOn(name, kj::str("Not defined: ", name.getValue())); return nullptr; } } case Expression::IMPORT: { auto filename = source.getImport(); KJ_IF_MAYBE(decl, resolver.resolveImport(filename.getValue())) { errorReporter.reportResolution(Resolution { /* .startByte = */ source.getStartByte(), /* .endByte = */ source.getEndByte(), /* .target = */ Resolution::Type { decl->id }, }); // Import is always a root scope, so create a fresh BrandScope. return BrandedDecl(*decl, kj::refcounted( errorReporter, decl->id, decl->genericParamCount, *decl->resolver), source); } else { errorReporter.addErrorOn(filename, kj::str("Import failed: ", filename.getValue())); return nullptr; } } case Expression::APPLICATION: { auto app = source.getApplication(); KJ_IF_MAYBE(decl, compileDeclExpression(app.getFunction(), resolver, implicitMethodParams)) { // Compile all params. auto params = app.getParams(); auto compiledParams = kj::heapArrayBuilder(params.size()); bool paramFailed = false; for (auto param: params) { if (param.isNamed()) { errorReporter.addErrorOn(param.getNamed(), "Named parameter not allowed here."); } KJ_IF_MAYBE(d, compileDeclExpression(param.getValue(), resolver, implicitMethodParams)) { compiledParams.add(kj::mv(*d)); } else { // Param failed to compile. Error was already reported. paramFailed = true; } }; if (paramFailed) { return kj::mv(*decl); } // Add the parameters to the brand. KJ_IF_MAYBE(applied, decl->applyParams(compiledParams.finish(), source)) { return kj::mv(*applied); } else { // Error already reported. Ignore parameters. return kj::mv(*decl); } } else { // error already reported return nullptr; } } case Expression::MEMBER: { auto member = source.getMember(); KJ_IF_MAYBE(decl, compileDeclExpression(member.getParent(), resolver, implicitMethodParams)) { auto name = member.getName(); KJ_IF_MAYBE(memberDecl, decl->getMember(name.getValue(), source)) { KJ_IF_MAYBE(id, memberDecl->getGenericTypeId()) { errorReporter.reportResolution(Resolution { /* .startByte = */ source.getStartByte(), /* .endByte = */ source.getEndByte(), /* .target = */ Resolution::Type { *id }, }); } return kj::mv(*memberDecl); } else { errorReporter.addErrorOn(name, kj::str( "'", expressionString(member.getParent()), "' has no member named '", name.getValue(), "'")); return nullptr; } } else { // error already reported return nullptr; } } } KJ_UNREACHABLE; } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/generics.h0000644000175000017500000003251314731420004022413 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2020 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include #include #include #include "error-reporter.h" #include "resolver.h" CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { class BrandedDecl; class BrandScope; struct ImplicitParams { // Represents a set of implicit brand parameters visible in the current context. // // As of this writing, implicit parameters occur only in the context of RPC methods. That is, // like this: // // makeBox @0 [T] (value :T) -> Box(T); // // Here, `T` is an implicit parameter. uint64_t scopeId; // If zero, then any reference to an implicit param in this context should be compiled to a // `implicitMethodParam` AnyPointer. If non-zero, it should be compiled to a `parameter` // AnyPointer using this scopeId. This comes into play when compiling the implicitly-generated // struct types corresponding to a method's params or results; these implicitly-generated types // themselves have *explicit* brand parameters corresponding to the *implicit* brand parameters // of the method. // // TODO(cleanup): Unclear why ImplicitParams is even used when compiling the implicit structs // with explicit params. Missing abstraction? List::Reader params; // Name and metadata about the parameter declaration. static inline ImplicitParams none() { // Convenience helper to create an empty `ImplicitParams`. return { 0, List::Reader() }; } }; class BrandedDecl { // Represents a declaration possibly with generic parameter bindings. public: inline BrandedDecl(Resolver::ResolvedDecl decl, kj::Own&& brand, Expression::Reader source) : brand(kj::mv(brand)), source(source) { // `source`, is the expression which specified this branded decl. It is provided so that errors // can be reported against it. It is acceptable to pass a default-initialized reader if there's // no source expression; errors will then be reported at 0, 0. body.init(kj::mv(decl)); } inline BrandedDecl(Resolver::ResolvedParameter variable, Expression::Reader source) : source(source) { body.init(kj::mv(variable)); } inline BrandedDecl(decltype(nullptr)) {} inline BrandedDecl() {} // exists only for ExternalMutexGuarded to work... static BrandedDecl implicitMethodParam(uint index) { // Get a BrandedDecl referring to an implicit method parameter. // (As a hack, we internally represent this as a ResolvedParameter. Sorry.) return BrandedDecl(Resolver::ResolvedParameter { 0, index }, Expression::Reader()); } BrandedDecl(BrandedDecl& other); BrandedDecl(BrandedDecl&& other) = default; BrandedDecl& operator=(BrandedDecl& other); BrandedDecl& operator=(BrandedDecl&& other) = default; kj::Maybe applyParams(kj::Array params, Expression::Reader subSource); // Treat the declaration as a generic and apply it to the given parameter list. kj::Maybe getMember(kj::StringPtr memberName, Expression::Reader subSource); // Get a member of this declaration. kj::Maybe getKind(); // Returns the kind of declaration, or null if this is an unbound generic variable. template uint64_t getIdAndFillBrand(InitBrandFunc&& initBrand); // Returns the type ID of this node. `initBrand` is a zero-arg functor which returns // schema::Brand::Builder; this will be called if this decl has brand bindings, and // the returned builder filled in to reflect those bindings. // // It is an error to call this when `getKind()` returns null. kj::Maybe getListParam(); // Only if the kind is BUILTIN_LIST: Get the list's type parameter. Resolver::ResolvedParameter asVariable(); // If this is an unbound generic variable (i.e. `getKind()` returns null), return information // about the variable. // // It is an error to call this when `getKind()` does not return null. bool compileAsType(ErrorReporter& errorReporter, schema::Type::Builder target); // Compile this decl to a schema::Type. inline void addError(ErrorReporter& errorReporter, kj::StringPtr message) { errorReporter.addErrorOn(source, message); } Resolver::ResolveResult asResolveResult(uint64_t scopeId, schema::Brand::Builder brandBuilder); // Reverse this into a ResolveResult. If necessary, use `brandBuilder` to fill in // ResolvedDecl.brand. kj::String toString(); kj::String toDebugString(); kj::Maybe getGenericTypeId() { // If this declaration points to a type, gets its type ID. Keep in mind that this // drops the brand, that is, if the type is the result of applying a generic to // some type parameters, this returns only the ID of the underlying generic type, // which loses information about the type parameters. if (body.is()) { return body.get().id; } return nullptr; } private: Resolver::ResolveResult body; kj::Own brand; // null if parameter Expression::Reader source; }; class BrandScope: public kj::Refcounted { // Tracks the brand parameter bindings affecting the scope specified by some expression. For // example, if we are interpreting the type expression "Foo(Text).Bar", we would start with the // current scope's BrandScope, create a new child BrandScope representing "Foo", add the "(Text)" // parameter bindings to it, then create a further child scope for "Bar". Thus the BrandScope for // Bar knows that Foo's parameter list has been bound to "(Text)". public: BrandScope(ErrorReporter& errorReporter, uint64_t startingScopeId, uint startingScopeParamCount, Resolver& startingScope); // TODO(bug): Passing an `errorReporter` to the constructor of `BrandScope` turns out not to // make a ton of sense, as an `errorReporter` is meant to report errors in a specific module, // but `BrandScope` might be constructed while compiling one module but then used when // compiling a different module, or not compiling a module at all. Note, though, that it DOES // make sense for BrandedDecl to have an ErrorReporter, specifically associated with its // `source` expression. bool isGeneric(); // Returns true if this scope or any parent scope is a generic (has brand parameters). kj::Own push(uint64_t typeId, uint paramCount); // Creates a new child scope with the given type ID and number of brand parameters. kj::Maybe> setParams( kj::Array params, Declaration::Which genericType, Expression::Reader source); // Create a new BrandScope representing the same scope, but with parameters filled in. // // This should only be called on the generic version of the scope. If called on a branded // version, an error will be reported. // // Returns null if an error occurred that prevented creating the BrandScope; the error will have // been reported to the ErrorReporter. kj::Own pop(uint64_t newLeafId); // Return the parent scope. kj::Maybe lookupParameter(Resolver& resolver, uint64_t scopeId, uint index); // Search up the scope chain for the scope matching `scopeId`, and return its `index`th parameter // binding. Returns null if the parameter is from a scope that we are currently compiling, and // hasn't otherwise been bound to any argument (see Brand.Scope.inherit in schema.capnp). // // In the case that a parameter wasn't specified, but isn't part of the current scope, this // returns the declaration for `AnyPointer`. // // TODO(cleanup): Should be called lookupArgument()? kj::Maybe> getParams(uint64_t scopeId); // Get the whole list of parameter bindings at the given scope. Returns null if the scope is // currently be compiled and the parameters are unbound. // // Note that it's possible that not all declared parameters were actually specified for a given // scope. For example, if you declare a generic `Foo(T, U)`, and then you intiantiate it // somewhere as `Foo(Text)`, then `U` is unspecified -- this is not an error, because Cap'n // Proto allows new type parameters to be added over time. `U` should be treated as `AnyPointer` // in this case, but `getParams()` doesn't know how many parameters are expected, so it will // return an array that only contains one item. Use `lookupParameter()` if you want unspecified // parameters to be filled in with `AnyPointer` automatically. // // TODO(cleanup): Should be called getArguments()? template void compile(InitBrandFunc&& initBrand); // Constructs the schema::Brand corresponding to this brand scope. // // `initBrand` is a zero-arg functor which returns an empty schema::Brand::Builder, into which // the brand is constructed. If no generics are present, then `initBrand` is never called. // // TODO(cleanup): Should this return Maybe> instead? kj::Maybe compileDeclExpression( Expression::Reader source, Resolver& resolver, ImplicitParams implicitMethodParams); // Interpret a type expression within this branded scope. BrandedDecl interpretResolve( Resolver& resolver, Resolver::ResolveResult& result, Expression::Reader source); // After using a Resolver to resolve a symbol, call interpretResolve() to interpret the result // within the current brand scope. For example, if a name resolved to a brand parameter, this // replaces it with the appropriate argument from the scope. inline uint64_t getScopeId() { return leafId; } private: ErrorReporter& errorReporter; kj::Maybe> parent; uint64_t leafId; // zero = this is the root uint leafParamCount; // number of generic parameters on this leaf bool inherited; kj::Array params; BrandScope(kj::Own parent, uint64_t leafId, uint leafParamCount) : errorReporter(parent->errorReporter), parent(kj::mv(parent)), leafId(leafId), leafParamCount(leafParamCount), inherited(false) {} BrandScope(BrandScope& base, kj::Array params) : errorReporter(base.errorReporter), leafId(base.leafId), leafParamCount(base.leafParamCount), inherited(false), params(kj::mv(params)) { KJ_IF_MAYBE(p, base.parent) { parent = kj::addRef(**p); } } BrandScope(ErrorReporter& errorReporter, uint64_t scopeId) : errorReporter(errorReporter), leafId(scopeId), leafParamCount(0), inherited(false) {} kj::Own evaluateBrand( Resolver& resolver, Resolver::ResolvedDecl decl, List::Reader brand, uint index = 0); BrandedDecl decompileType(Resolver& resolver, schema::Type::Reader type); template friend kj::Own kj::refcounted(Params&&... params); friend class BrandedDecl; }; template uint64_t BrandedDecl::getIdAndFillBrand(InitBrandFunc&& initBrand) { KJ_REQUIRE(body.is()); brand->compile(kj::fwd(initBrand)); return body.get().id; } template void BrandScope::compile(InitBrandFunc&& initBrand) { kj::Vector levels; BrandScope* ptr = this; for (;;) { if (ptr->params.size() > 0 || (ptr->inherited && ptr->leafParamCount > 0)) { levels.add(ptr); } KJ_IF_MAYBE(p, ptr->parent) { ptr = *p; } else { break; } } if (levels.size() > 0) { auto scopes = initBrand().initScopes(levels.size()); for (uint i: kj::indices(levels)) { auto scope = scopes[i]; scope.setScopeId(levels[i]->leafId); if (levels[i]->inherited) { scope.setInherit(); } else { auto bindings = scope.initBind(levels[i]->params.size()); for (uint j: kj::indices(bindings)) { levels[i]->params[j].compileAsType(errorReporter, bindings[j].initType()); } } } } } } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/parser.c++0000644000175000017500000014175014712011043022233 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #if _WIN32 #include #endif #include "parser.h" #include "type-id.h" #include #include #include #if !_MSC_VER #include #endif #include #include #include #if _WIN32 #include #include #undef CONST #include #endif namespace capnp { namespace compiler { uint64_t generateRandomId() { uint64_t result; #if _WIN32 HCRYPTPROV handle; KJ_ASSERT(CryptAcquireContextW(&handle, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)); KJ_DEFER(KJ_ASSERT(CryptReleaseContext(handle, 0)) {break;}); KJ_ASSERT(CryptGenRandom(handle, sizeof(result), reinterpret_cast(&result))); #else int fd; KJ_SYSCALL(fd = open("/dev/urandom", O_RDONLY)); KJ_DEFER(close(fd)); ssize_t n; KJ_SYSCALL(n = read(fd, &result, sizeof(result)), "/dev/urandom"); KJ_ASSERT(n == sizeof(result), "Incomplete read from /dev/urandom.", n); #endif return result | (1ull << 63); } void parseFile(List::Reader statements, ParsedFile::Builder result, ErrorReporter& errorReporter, bool requiresId) { CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter); kj::Vector> decls(statements.size()); kj::Vector> annotations; auto fileDecl = result.getRoot(); fileDecl.setFile(VOID); for (auto statement: statements) { KJ_IF_MAYBE(decl, parser.parseStatement(statement, parser.getParsers().fileLevelDecl)) { Declaration::Builder builder = decl->get(); switch (builder.which()) { case Declaration::NAKED_ID: if (fileDecl.getId().isUid()) { errorReporter.addError(builder.getStartByte(), builder.getEndByte(), "File can only have one ID."); } else { fileDecl.getId().adoptUid(builder.disownNakedId()); if (builder.hasDocComment()) { fileDecl.adoptDocComment(builder.disownDocComment()); } } break; case Declaration::NAKED_ANNOTATION: annotations.add(builder.disownNakedAnnotation()); break; default: decls.add(kj::mv(*decl)); break; } } } if (fileDecl.getId().which() != Declaration::Id::UID) { // We didn't see an ID. Generate one randomly for now. uint64_t id = generateRandomId(); fileDecl.getId().initUid().setValue(id); // Don't report missing ID if there was a parse error, because quite often the parse error // prevents us from parsing the ID even though it is actually there. if (requiresId && !errorReporter.hadErrors()) { errorReporter.addError(0, 0, kj::str("File does not declare an ID. I've generated one for you. Add this line to " "your file: @0x", kj::hex(id), ";")); } } auto declsBuilder = fileDecl.initNestedDecls(decls.size()); for (size_t i = 0; i < decls.size(); i++) { declsBuilder.adoptWithCaveats(i, kj::mv(decls[i])); } auto annotationsBuilder = fileDecl.initAnnotations(annotations.size()); for (size_t i = 0; i < annotations.size(); i++) { annotationsBuilder.adoptWithCaveats(i, kj::mv(annotations[i])); } } namespace p = kj::parse; namespace { // ======================================================================================= template struct Located { T value; uint32_t startByte; uint32_t endByte; template void copyLocationTo(Builder builder) { builder.setStartByte(startByte); builder.setEndByte(endByte); } template void copyTo(Builder builder) { builder.setValue(value); copyLocationTo(builder); } template Orphan asProto(Orphanage orphanage) { auto result = orphanage.newOrphan(); copyTo(result.get()); return result; } template Located> rewrap(Other&& other) { return Located(kj::fwd(other), startByte, endByte); } Located(const T& value, uint32_t startByte, uint32_t endByte) : value(value), startByte(startByte), endByte(endByte) {} Located(T&& value, uint32_t startByte, uint32_t endByte) : value(kj::mv(value)), startByte(startByte), endByte(endByte) {} }; // ======================================================================================= template struct MatchTokenType { kj::Maybe> operator()(Token::Reader token) const { if (token.which() == type) { return Located((token.*get)(), token.getStartByte(), token.getEndByte()); } else { return nullptr; } } }; #define TOKEN_TYPE_PARSER(type, discrim, getter) \ p::transformOrReject(p::any, \ MatchTokenType()) constexpr auto identifier = TOKEN_TYPE_PARSER(Text::Reader, IDENTIFIER, getIdentifier); constexpr auto stringLiteral = TOKEN_TYPE_PARSER(Text::Reader, STRING_LITERAL, getStringLiteral); constexpr auto binaryLiteral = TOKEN_TYPE_PARSER(Data::Reader, BINARY_LITERAL, getBinaryLiteral); constexpr auto integerLiteral = TOKEN_TYPE_PARSER(uint64_t, INTEGER_LITERAL, getIntegerLiteral); constexpr auto floatLiteral = TOKEN_TYPE_PARSER(double, FLOAT_LITERAL, getFloatLiteral); constexpr auto operatorToken = TOKEN_TYPE_PARSER(Text::Reader, OPERATOR, getOperator); constexpr auto rawParenthesizedList = TOKEN_TYPE_PARSER(List>::Reader, PARENTHESIZED_LIST, getParenthesizedList); constexpr auto rawBracketedList = TOKEN_TYPE_PARSER(List>::Reader, BRACKETED_LIST, getBracketedList); // ======================================================================================= class ExactString { public: constexpr ExactString(const char* expected): expected(expected) {} kj::Maybe> operator()(Located&& text) const { if (text.value == expected) { return kj::Tuple<>(); } else { return nullptr; } } private: const char* expected; }; constexpr auto keyword(const char* expected) -> decltype(p::transformOrReject(identifier, ExactString(expected))) { return p::transformOrReject(identifier, ExactString(expected)); } constexpr auto op(const char* expected) -> decltype(p::transformOrReject(operatorToken, ExactString(expected))) { return p::transformOrReject(operatorToken, ExactString(expected)); } class LocatedExactString { public: constexpr LocatedExactString(const char* expected): expected(expected) {} kj::Maybe> operator()(Located&& text) const { if (text.value == expected) { return kj::mv(text); } else { return nullptr; } } private: const char* expected; }; constexpr auto locatedKeyword(const char* expected) -> decltype(p::transformOrReject(identifier, LocatedExactString(expected))) { return p::transformOrReject(identifier, LocatedExactString(expected)); } // ======================================================================================= template class ParseListItems { // Transformer that parses all items in the input token sequence list using the given parser. public: constexpr ParseListItems(ItemParser&& itemParser, ErrorReporter& errorReporter) : itemParser(p::sequence(kj::fwd(itemParser), p::endOfInput)), errorReporter(errorReporter) {} Located>>> operator()( Located>::Reader>&& items) const { auto result = kj::heapArray>>( items.value.size()); for (uint i = 0; i < items.value.size(); i++) { auto item = items.value[i]; CapnpParser::ParserInput input(item.begin(), item.end()); result[i] = itemParser(input); if (result[i] == nullptr) { // Parsing failed. Report an error. auto best = input.getBest(); if (best < item.end()) { // Report error from the point where parsing failed to the end of the item. errorReporter.addError( best->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error."); } else if (item.size() > 0) { // The item is non-empty and the parser consumed all of it before failing. Report an // error for the whole thing. errorReporter.addError( item.begin()->getStartByte(), (item.end() - 1)->getEndByte(), "Parse error."); } else { // The item has no content. // TODO(cleanup): We don't actually know the item's location, so we can only report // an error across the whole list. Fix this. errorReporter.addError(items.startByte, items.endByte, "Parse error: Empty list item."); } } } return Located>>>( kj::mv(result), items.startByte, items.endByte); } private: decltype(p::sequence(kj::instance(), p::endOfInput)) itemParser; ErrorReporter& errorReporter; }; template constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype( transform(rawParenthesizedList, ParseListItems( kj::fwd(itemParser), errorReporter))) { return transform(rawParenthesizedList, ParseListItems( kj::fwd(itemParser), errorReporter)); } template constexpr auto bracketedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype( transform(rawBracketedList, ParseListItems( kj::fwd(itemParser), errorReporter))) { return transform(rawBracketedList, ParseListItems( kj::fwd(itemParser), errorReporter)); } // ======================================================================================= template Orphan> arrayToList(Orphanage& orphanage, kj::Array>&& elements) { auto result = orphanage.newOrphan>(elements.size()); auto builder = result.get(); for (size_t i = 0; i < elements.size(); i++) { builder.adoptWithCaveats(i, kj::mv(elements[i])); } return kj::mv(result); } static void initGenericParams(Declaration::Builder builder, kj::Maybe>>>>&& genericParameters) { KJ_IF_MAYBE(p, genericParameters) { auto params = builder.initParameters(p->value.size()); for (uint i: kj::indices(p->value)) { KJ_IF_MAYBE(name, p->value[i]) { auto param = params[i]; param.setName(name->value); name->copyLocationTo(param); } } } } static Declaration::Builder initDecl( Declaration::Builder builder, Located&& name, kj::Maybe>&& id, kj::Maybe>>>>&& genericParameters, kj::Array>&& annotations) { name.copyTo(builder.initName()); KJ_IF_MAYBE(i, id) { builder.getId().adoptUid(kj::mv(*i)); } initGenericParams(builder, kj::mv(genericParameters)); auto list = builder.initAnnotations(annotations.size()); for (uint i = 0; i < annotations.size(); i++) { list.adoptWithCaveats(i, kj::mv(annotations[i])); } return builder; } static Declaration::Builder initMemberDecl( Declaration::Builder builder, Located&& name, Orphan&& ordinal, kj::Array>&& annotations) { name.copyTo(builder.initName()); builder.getId().adoptOrdinal(kj::mv(ordinal)); auto list = builder.initAnnotations(annotations.size()); for (uint i = 0; i < annotations.size(); i++) { list.adoptWithCaveats(i, kj::mv(annotations[i])); } return builder; } template void initLocation(kj::parse::Span::Reader::Iterator> location, BuilderType builder) { if (location.begin() < location.end()) { builder.setStartByte(location.begin()->getStartByte()); builder.setEndByte((location.end() - 1)->getEndByte()); } } } // namespace // ======================================================================================= CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterParam) : orphanage(orphanageParam), errorReporter(errorReporterParam) { auto& tupleElement = arena.copy(p::transform( p::sequence(p::optional(p::sequence(identifier, op("="))), parsers.expression), [this](kj::Maybe>&& fieldName, Orphan&& fieldValue) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); KJ_IF_MAYBE(fn, fieldName) { fn->copyTo(builder.initNamed()); } else { builder.setUnnamed(); } builder.adoptValue(kj::mv(fieldValue)); return kj::mv(result); })); auto& tuple = arena.copy>>>>( arena.copy(p::transform( parenthesizedList(tupleElement, errorReporter), [this](Located>>>&& elements) -> Located>> { auto result = orphanage.newOrphan>(elements.value.size()); auto builder = result.get(); for (uint i: kj::indices(elements.value)) { KJ_IF_MAYBE(e, elements.value[i]) { builder.adoptWithCaveats(i, kj::mv(*e)); } else { builder[i].initValue().setUnknown(); } } return elements.rewrap(kj::mv(result)); }))); parsers.expression = arena.copy(p::transform( p::sequence( // Base expression. p::oneOf( p::transform(integerLiteral, [this](Located&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setPositiveInt(value.value); value.copyLocationTo(builder); return result; }), p::transform(p::sequence(op("-"), integerLiteral), [this](Located&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setNegativeInt(value.value); value.copyLocationTo(builder); return result; }), p::transform(floatLiteral, [this](Located&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setFloat(value.value); value.copyLocationTo(builder); return result; }), p::transform(p::sequence(op("-"), floatLiteral), [this](Located&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setFloat(-value.value); value.copyLocationTo(builder); return result; }), p::transformWithLocation(p::sequence(op("-"), keyword("inf")), [this](kj::parse::Span::Reader::Iterator> location) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setFloat(-kj::inf()); initLocation(location, builder); return result; }), p::transform(p::oneOrMore(stringLiteral), [this](kj::Array>&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setString(kj::strArray( KJ_MAP(part, value) { return part.value; }, "")); builder.setStartByte(value.front().startByte); builder.setEndByte(value.back().endByte); return result; }), p::transform(binaryLiteral, [this](Located&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.setBinary(value.value); value.copyLocationTo(builder); return result; }), p::transform(bracketedList(parsers.expression, errorReporter), [this](Located>>>&& value) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); auto listBuilder = builder.initList(value.value.size()); for (uint i = 0; i < value.value.size(); i++) { KJ_IF_MAYBE(element, value.value[i]) { listBuilder.adoptWithCaveats(i, kj::mv(*element)); } } value.copyLocationTo(builder); return result; }), p::transform(tuple, [this](Located>>&& value) -> Orphan { auto elements = value.value.get(); if (elements.size() == 1 && elements[0].isUnnamed()) { // Single-value tuple is just a value. return elements[0].disownValue(); } else { auto result = orphanage.newOrphan(); auto builder = result.get(); builder.adoptTuple(kj::mv(value.value)); value.copyLocationTo(builder); return result; } }), p::transformWithLocation(p::sequence(keyword("import"), stringLiteral), [this](kj::parse::Span::Reader::Iterator> location, Located&& filename) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); initLocation(location, builder); filename.copyTo(builder.initImport()); return result; }), p::transformWithLocation(p::sequence(keyword("embed"), stringLiteral), [this](kj::parse::Span::Reader::Iterator> location, Located&& filename) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); initLocation(location, builder); filename.copyTo(builder.initEmbed()); return result; }), p::transformWithLocation(p::sequence(op("."), identifier), [this](kj::parse::Span::Reader::Iterator> location, Located&& name) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); initLocation(location, builder); name.copyTo(builder.initAbsoluteName()); return result; }), p::transform(identifier, [this](Located&& name) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); name.copyTo(builder.initRelativeName()); name.copyLocationTo(builder); return result; })), // Suffixes, e.g. ".member" or "(param1, param2)". p::many(p::oneOf( p::transformWithLocation(p::sequence(op("."), identifier), [this](kj::parse::Span::Reader::Iterator> location, Located&& name) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); initLocation(location, builder); name.copyTo(builder.initMember().initName()); return result; }), p::transform(tuple, [this](Located>>&& params) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); params.copyLocationTo(builder); builder.initApplication().adoptParams(kj::mv(params.value)); return result; })))), [](Orphan&& base, kj::Array>&& suffixes) -> Orphan { // Apply all the suffixes to the base expression. uint startByte = base.getReader().getStartByte(); for (auto& suffix: suffixes) { auto builder = suffix.get(); if (builder.isApplication()) { builder.getApplication().adoptFunction(kj::mv(base)); } else if (builder.isMember()) { builder.getMember().adoptParent(kj::mv(base)); } else { KJ_FAIL_ASSERT("Unknown suffix?", (uint)builder.which()); } builder.setStartByte(startByte); base = kj::mv(suffix); } return kj::mv(base); })); parsers.annotation = arena.copy(p::transform( p::sequence(op("$"), parsers.expression), [this](Orphan&& expression) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); auto exp = expression.get(); if (exp.isApplication()) { // Oops, this annotation specifies the value, but we parsed it as an application on // the preceding expression. Pull it back apart. auto app = exp.getApplication(); builder.adoptName(app.disownFunction()); auto params = app.getParams(); if (params.size() == 1 && params[0].isUnnamed()) { // Params has a single unnamed element, so reduce it to a simple value rather than // a tuple. builder.getValue().adoptExpression(params[0].disownValue()); } else { // Params is not a single unnamed element, so it's a tuple. builder.getValue().initExpression().adoptTuple(app.disownParams()); } } else { // The annotation has no value. builder.adoptName(kj::mv(expression)); builder.getValue().setNone(); } return result; })); parsers.uid = arena.copy(p::transform( p::sequence(op("@"), integerLiteral), [this](Located&& value) { if (value.value < (1ull << 63)) { errorReporter.addError(value.startByte, value.endByte, "Invalid ID. Please generate a new one with 'capnpc -i'."); } return value.asProto(orphanage); })); parsers.ordinal = arena.copy(p::transform( p::sequence(op("@"), integerLiteral), [this](Located&& value) { if (value.value >= 65536) { errorReporter.addError(value.startByte, value.endByte, "Ordinals cannot be greater than 65535."); } return value.asProto(orphanage); })); // ----------------------------------------------------------------- parsers.usingDecl = arena.copy(p::transform( p::sequence(keyword("using"), p::optional(p::sequence(identifier, op("="))), parsers.expression), [this](kj::Maybe>&& name, Orphan&& target) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = decl.get(); KJ_IF_MAYBE(n, name) { n->copyTo(builder.initName()); } else { auto targetReader = target.getReader(); if (targetReader.isMember()) { builder.setName(targetReader.getMember().getName()); } else { errorReporter.addErrorOn(targetReader, "'using' declaration without '=' must specify a named declaration from a " "different scope."); } } // no id, no annotations for using decl builder.initUsing().adoptTarget(kj::mv(target)); return DeclParserResult(kj::mv(decl)); })); parsers.constDecl = arena.copy(p::transform( p::sequence(keyword("const"), identifier, p::optional(parsers.uid), op(":"), parsers.expression, op("="), parsers.expression, p::many(parsers.annotation)), [this](Located&& name, kj::Maybe>&& id, Orphan&& type, Orphan&& value, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).initConst(); builder.adoptType(kj::mv(type)); builder.adoptValue(kj::mv(value)); return DeclParserResult(kj::mv(decl)); })); parsers.enumDecl = arena.copy(p::transform( p::sequence(keyword("enum"), identifier, p::optional(parsers.uid), p::many(parsers.annotation)), [this](Located&& name, kj::Maybe>&& id, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).setEnum(); return DeclParserResult(kj::mv(decl), parsers.enumLevelDecl); })); parsers.enumerantDecl = arena.copy(p::transform( p::sequence(identifier, parsers.ordinal, p::many(parsers.annotation)), [this](Located&& name, Orphan&& ordinal, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)) .setEnumerant(); return DeclParserResult(kj::mv(decl)); })); parsers.structDecl = arena.copy(p::transform( p::sequence(keyword("struct"), identifier, p::optional(parsers.uid), p::optional(parenthesizedList(identifier, errorReporter)), p::many(parsers.annotation)), [this](Located&& name, kj::Maybe>&& id, kj::Maybe>>>>&& genericParameters, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); initDecl(decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters), kj::mv(annotations)).setStruct(); return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); })); parsers.fieldDecl = arena.copy(p::transform( p::sequence(identifier, parsers.ordinal, op(":"), parsers.expression, p::optional(p::sequence(op("="), parsers.expression)), p::many(parsers.annotation)), [this](Located&& name, Orphan&& ordinal, Orphan&& type, kj::Maybe>&& defaultValue, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)) .initField(); builder.adoptType(kj::mv(type)); KJ_IF_MAYBE(val, defaultValue) { builder.getDefaultValue().adoptValue(kj::mv(*val)); } else { builder.getDefaultValue().setNone(); } return DeclParserResult(kj::mv(decl)); })); // Parse an ordinal followed by an optional colon, or no ordinal but require a colon. auto& ordinalOrColon = arena.copy(p::oneOf( p::transform(p::sequence(parsers.ordinal, p::optional(op("!")), p::optional(op(":"))), [](Orphan&& ordinal, kj::Maybe> exclamation, kj::Maybe> colon) -> kj::Tuple>, bool, bool> { return kj::tuple(kj::mv(ordinal), exclamation == nullptr, colon == nullptr); }), p::transform(op(":"), []() -> kj::Tuple>, bool, bool> { return kj::tuple(nullptr, false, false); }))); parsers.unionDecl = arena.copy(p::transform( // The first branch of this oneOf() matches named unions. The second branch matches unnamed // unions and generates dummy values for the parse results. p::oneOf( p::sequence( identifier, ordinalOrColon, keyword("union"), p::many(parsers.annotation)), p::transformWithLocation(p::sequence(keyword("union"), p::endOfInput), [](kj::parse::Span::Reader::Iterator> location) { return kj::tuple( Located("", location.begin()->getStartByte(), location.begin()->getEndByte()), kj::Maybe>(nullptr), false, false, kj::Array>(nullptr)); })), [this](Located&& name, kj::Maybe>&& ordinal, bool missingExclamation, bool missingColon, kj::Array>&& annotations) -> DeclParserResult { if (missingExclamation) { errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(), "As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to " "unions. However, removing the number will break binary compatibility. " "If this is an old protocol and you need to retain compatibility, please " "add an exclamation point after the number to indicate that it is really " "needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility " "doesn't matter, just remove the @n entirely. Sorry for the inconvenience, " "and thanks for being an early adopter! :)"); } if (missingColon) { errorReporter.addErrorOn(KJ_ASSERT_NONNULL(ordinal).getReader(), "As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon " "for named unions, e.g. `foo :union {`."); } auto decl = orphanage.newOrphan(); auto builder = decl.get(); name.copyTo(builder.initName()); KJ_IF_MAYBE(ord, ordinal) { builder.getId().adoptOrdinal(kj::mv(*ord)); } else { builder.getId().setUnspecified(); } auto list = builder.initAnnotations(annotations.size()); for (uint i = 0; i < annotations.size(); i++) { list.adoptWithCaveats(i, kj::mv(annotations[i])); } builder.setUnion(); return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); })); parsers.groupDecl = arena.copy(p::transform( p::sequence(identifier, op(":"), keyword("group"), p::many(parsers.annotation)), [this](Located&& name, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = decl.get(); name.copyTo(builder.getName()); builder.getId().setUnspecified(); auto list = builder.initAnnotations(annotations.size()); for (uint i = 0; i < annotations.size(); i++) { list.adoptWithCaveats(i, kj::mv(annotations[i])); } builder.setGroup(); return DeclParserResult(kj::mv(decl), parsers.structLevelDecl); })); parsers.interfaceDecl = arena.copy(p::transform( p::sequence(keyword("interface"), identifier, p::optional(parsers.uid), p::optional(parenthesizedList(identifier, errorReporter)), p::optional(p::sequence( keyword("extends"), parenthesizedList(parsers.expression, errorReporter))), p::many(parsers.annotation)), [this](Located&& name, kj::Maybe>&& id, kj::Maybe>>>>&& genericParameters, kj::Maybe>>>>&& superclasses, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = initDecl( decl.get(), kj::mv(name), kj::mv(id), kj::mv(genericParameters), kj::mv(annotations)).initInterface(); KJ_IF_MAYBE(s, superclasses) { auto superclassesBuilder = builder.initSuperclasses(s->value.size()); for (uint i: kj::indices(s->value)) { KJ_IF_MAYBE(superclass, s->value[i]) { superclassesBuilder.adoptWithCaveats(i, kj::mv(*superclass)); } } } return DeclParserResult(kj::mv(decl), parsers.interfaceLevelDecl); })); parsers.param = arena.copy(p::transformWithLocation( p::sequence(identifier, op(":"), parsers.expression, p::optional(p::sequence(op("="), parsers.expression)), p::many(parsers.annotation)), [this](kj::parse::Span::Reader::Iterator> location, Located&& name, Orphan&& type, kj::Maybe>&& defaultValue, kj::Array>&& annotations) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); initLocation(location, builder); name.copyTo(builder.initName()); builder.adoptType(kj::mv(type)); builder.adoptAnnotations(arrayToList(orphanage, kj::mv(annotations))); KJ_IF_MAYBE(val, defaultValue) { builder.getDefaultValue().adoptValue(kj::mv(*val)); } else { builder.getDefaultValue().setNone(); } return kj::mv(result); })); auto& paramList = arena.copy(p::oneOf( p::transform(parenthesizedList(parsers.param, errorReporter), [this](Located>>>&& params) -> Orphan { auto decl = orphanage.newOrphan(); auto builder = decl.get(); params.copyLocationTo(builder); auto listBuilder = builder.initNamedList(params.value.size()); for (uint i: kj::indices(params.value)) { KJ_IF_MAYBE(param, params.value[i]) { listBuilder.adoptWithCaveats(i, kj::mv(*param)); } } return decl; }), p::transform(locatedKeyword("stream"), [this](Located&& kw) -> Orphan { auto decl = orphanage.newOrphan(); auto builder = decl.get(); kw.copyLocationTo(builder); builder.setStream(); return decl; }), p::transform(parsers.expression, [this](Orphan&& name) -> Orphan { auto decl = orphanage.newOrphan(); auto builder = decl.get(); auto nameReader = name.getReader(); builder.setStartByte(nameReader.getStartByte()); builder.setEndByte(nameReader.getEndByte()); builder.adoptType(kj::mv(name)); return decl; }))); parsers.methodDecl = arena.copy(p::transform( p::sequence(identifier, parsers.ordinal, p::optional(bracketedList(identifier, errorReporter)), paramList, p::optional(p::sequence(op("->"), paramList)), p::many(parsers.annotation)), [this](Located&& name, Orphan&& ordinal, kj::Maybe>>>>&& genericParams, Orphan&& params, kj::Maybe>&& results, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto nodeBuilder = initMemberDecl( decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations)); initGenericParams(nodeBuilder, kj::mv(genericParams)); auto builder = nodeBuilder.initMethod(); builder.adoptParams(kj::mv(params)); KJ_IF_MAYBE(r, results) { builder.getResults().adoptExplicit(kj::mv(*r)); } else { builder.getResults().setNone(); } return DeclParserResult(kj::mv(decl)); })); auto& annotationTarget = arena.copy(p::oneOf( identifier, p::transformWithLocation(op("*"), [](kj::parse::Span::Reader::Iterator> location) { // Hacky... return Located("*", location.begin()->getStartByte(), location.begin()->getEndByte()); }))); parsers.annotationDecl = arena.copy(p::transform( p::sequence(keyword("annotation"), identifier, p::optional(parsers.uid), parenthesizedList(annotationTarget, errorReporter), op(":"), parsers.expression, p::many(parsers.annotation)), [this](Located&& name, kj::Maybe>&& id, Located>>>&& targets, Orphan&& type, kj::Array>&& annotations) -> DeclParserResult { auto decl = orphanage.newOrphan(); auto builder = initDecl(decl.get(), kj::mv(name), kj::mv(id), nullptr, kj::mv(annotations)).initAnnotation(); builder.adoptType(kj::mv(type)); DynamicStruct::Builder dynamicBuilder = builder; for (auto& maybeTarget: targets.value) { KJ_IF_MAYBE(target, maybeTarget) { if (target->value == "*") { // Set all. if (targets.value.size() > 1) { errorReporter.addError(target->startByte, target->endByte, "Wildcard should not be specified together with other targets."); } for (auto field: dynamicBuilder.getSchema().getFields()) { if (field.getProto().getName().startsWith("targets")) { dynamicBuilder.set(field, true); } } } else { if (target->value.size() == 0 || target->value.size() >= 32 || target->value[0] < 'a' || target->value[0] > 'z') { errorReporter.addError(target->startByte, target->endByte, "Not a valid annotation target."); } else { char buffer[64]; strcpy(buffer, "targets"); strcat(buffer, target->value.cStr()); buffer[strlen("targets")] += 'A' - 'a'; KJ_IF_MAYBE(field, dynamicBuilder.getSchema().findFieldByName(buffer)) { if (dynamicBuilder.get(*field).as()) { errorReporter.addError(target->startByte, target->endByte, "Duplicate target specification."); } dynamicBuilder.set(*field, true); } else { errorReporter.addError(target->startByte, target->endByte, "Not a valid annotation target."); } } } } } return DeclParserResult(kj::mv(decl)); })); // ----------------------------------------------------------------- auto& nakedId = arena.copy(p::transform(parsers.uid, [this](Orphan&& value) -> DeclParserResult { auto decl = orphanage.newOrphan(); decl.get().adoptNakedId(kj::mv(value)); return DeclParserResult(kj::mv(decl)); })); auto& nakedAnnotation = arena.copy(p::transform(parsers.annotation, [this](Orphan&& value) -> DeclParserResult { auto decl = orphanage.newOrphan(); decl.get().adoptNakedAnnotation(kj::mv(value)); return DeclParserResult(kj::mv(decl)); })); // ----------------------------------------------------------------- parsers.genericDecl = arena.copy(p::oneOf( parsers.usingDecl, parsers.constDecl, parsers.annotationDecl, parsers.enumDecl, parsers.structDecl, parsers.interfaceDecl)); parsers.fileLevelDecl = arena.copy(p::oneOf( parsers.genericDecl, nakedId, nakedAnnotation)); parsers.enumLevelDecl = arena.copy(p::oneOf(parsers.enumerantDecl)); parsers.structLevelDecl = arena.copy(p::oneOf( parsers.unionDecl, parsers.fieldDecl, parsers.groupDecl, parsers.genericDecl)); parsers.interfaceLevelDecl = arena.copy(p::oneOf( parsers.methodDecl, parsers.genericDecl)); } CapnpParser::~CapnpParser() noexcept(false) {} kj::Maybe> CapnpParser::parseStatement( Statement::Reader statement, const DeclParser& parser) { auto fullParser = p::sequence(parser, p::endOfInput); auto tokens = statement.getTokens(); ParserInput parserInput(tokens.begin(), tokens.end()); KJ_IF_MAYBE(output, fullParser(parserInput)) { auto builder = output->decl.get(); if (statement.hasDocComment()) { builder.setDocComment(statement.getDocComment()); } builder.setStartByte(statement.getStartByte()); builder.setEndByte(statement.getEndByte()); switch (statement.which()) { case Statement::LINE: if (output->memberParser != nullptr) { errorReporter.addError(statement.getStartByte(), statement.getEndByte(), "This statement should end with a block, not a semicolon."); } break; case Statement::BLOCK: KJ_IF_MAYBE(memberParser, output->memberParser) { auto memberStatements = statement.getBlock(); kj::Vector> members(memberStatements.size()); for (auto memberStatement: memberStatements) { KJ_IF_MAYBE(member, parseStatement(memberStatement, *memberParser)) { members.add(kj::mv(*member)); } } builder.adoptNestedDecls(arrayToList(orphanage, members.releaseAsArray())); } else { errorReporter.addError(statement.getStartByte(), statement.getEndByte(), "This statement should end with a semicolon, not a block."); } break; } return kj::mv(output->decl); } else { // Parse error. Figure out where to report it. auto best = parserInput.getBest(); uint32_t bestByte; if (best != tokens.end()) { bestByte = best->getStartByte(); } else if (tokens.end() != tokens.begin()) { bestByte = (tokens.end() - 1)->getEndByte(); } else { bestByte = statement.getStartByte(); } errorReporter.addError(bestByte, bestByte, "Parse error."); return nullptr; } } // ======================================================================================= static const char HEXDIGITS[] = "0123456789abcdef"; static kj::StringTree stringLiteralStringTree(kj::StringPtr chars) { return kj::strTree('"', kj::encodeCEscape(chars), '"'); } static kj::StringTree binaryLiteralStringTree(Data::Reader data) { kj::Vector escaped(data.size() * 3); for (byte b: data) { escaped.add(HEXDIGITS[b % 16]); escaped.add(HEXDIGITS[b / 16]); escaped.add(' '); } escaped.removeLast(); return kj::strTree("0x\"", escaped, '"'); } static kj::StringTree expressionStringTree(Expression::Reader exp); static kj::StringTree tupleLiteral(List::Reader params) { auto parts = kj::heapArrayBuilder(params.size()); for (auto param: params) { auto part = expressionStringTree(param.getValue()); if (param.isNamed()) { part = kj::strTree(param.getNamed().getValue(), " = ", kj::mv(part)); } parts.add(kj::mv(part)); } return kj::strTree("( ", kj::StringTree(parts.finish(), ", "), " )"); } static kj::StringTree expressionStringTree(Expression::Reader exp) { switch (exp.which()) { case Expression::UNKNOWN: return kj::strTree(""); case Expression::POSITIVE_INT: return kj::strTree(exp.getPositiveInt()); case Expression::NEGATIVE_INT: return kj::strTree('-', exp.getNegativeInt()); case Expression::FLOAT: return kj::strTree(exp.getFloat()); case Expression::STRING: return stringLiteralStringTree(exp.getString()); case Expression::BINARY: return binaryLiteralStringTree(exp.getBinary()); case Expression::RELATIVE_NAME: return kj::strTree(exp.getRelativeName().getValue()); case Expression::ABSOLUTE_NAME: return kj::strTree('.', exp.getAbsoluteName().getValue()); case Expression::IMPORT: return kj::strTree("import ", stringLiteralStringTree(exp.getImport().getValue())); case Expression::EMBED: return kj::strTree("embed ", stringLiteralStringTree(exp.getEmbed().getValue())); case Expression::LIST: { auto list = exp.getList(); auto parts = kj::heapArrayBuilder(list.size()); for (auto element: list) { parts.add(expressionStringTree(element)); } return kj::strTree("[ ", kj::StringTree(parts.finish(), ", "), " ]"); } case Expression::TUPLE: return tupleLiteral(exp.getTuple()); case Expression::APPLICATION: { auto app = exp.getApplication(); return kj::strTree(expressionStringTree(app.getFunction()), '(', tupleLiteral(app.getParams()), ')'); } case Expression::MEMBER: { auto member = exp.getMember(); return kj::strTree(expressionStringTree(member.getParent()), '.', member.getName().getValue()); } } KJ_UNREACHABLE; } kj::String expressionString(Expression::Reader name) { return expressionStringTree(name).flatten(); } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/lexer-test.c++0000644000175000017500000003073414527152321023043 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "lexer.h" #include "../message.h" #include namespace capnp { namespace compiler { namespace { class TestFailingErrorReporter: public ErrorReporter { public: void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { KJ_FAIL_EXPECT("Parse failed.", startByte, endByte, message); } bool hadErrors() override { // Not used by lexer. return false; } }; template kj::String doLex(kj::StringPtr constText) { // Parse the given string into the given Cap'n Proto struct type using lex(), then stringify the // result and return that string. Additionally, single quotes in the input are converted to // double quotes, and double quotes in the output are converted to single quotes, to reduce the // amount of escaping needed in the test strings. // // Comparing stringifications against golden strings is ugly and brittle. If we had a // text-format parser we could use that. Except that said parser would probably be built on // the very lexer being tested here, so... maybe this is the best we can reasonably do. kj::String text = heapString(constText); for (char& c: text) { // Make it easier to write input strings below. if (c == '\'') c = '\"'; } MallocMessageBuilder message; auto file = message.initRoot(); TestFailingErrorReporter errorReporter; EXPECT_TRUE(lex(text, file, errorReporter)); kj::String result = kj::str(file); for (char& c: result) { // Make it easier to write golden strings below. if (c == '\"') c = '\''; } return result; } TEST(Lexer, Tokens) { EXPECT_STREQ( "(tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3), " "(identifier = 'bar', startByte = 4, endByte = 7)" "])", doLex("foo bar").cStr()); EXPECT_STREQ( "(tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3), " "(identifier = 'bar', startByte = 15, endByte = 18)" "])", doLex("foo # comment\n bar").cStr()); EXPECT_STREQ( "(tokens = [" "(stringLiteral = 'foo ', startByte = 2, endByte = 11), " "(integerLiteral = 123, startByte = 12, endByte = 15), " "(floatLiteral = 2.75, startByte = 16, endByte = 20), " "(floatLiteral = 60000, startByte = 21, endByte = 24), " "(operator = '+', startByte = 25, endByte = 26), " "(operator = '-=', startByte = 27, endByte = 29)" "])", doLex(" 'foo\\x20' 123 2.75 6e4 + -= ").cStr()); EXPECT_STREQ( "(tokens = [" "(parenthesizedList = [" "[" "(identifier = 'foo', startByte = 1, endByte = 4), " "(identifier = 'bar', startByte = 5, endByte = 8)" "], [" "(identifier = 'baz', startByte = 10, endByte = 13), " "(identifier = 'qux', startByte = 14, endByte = 17)" "], [" "(identifier = 'corge', startByte = 19, endByte = 24), " "(identifier = 'grault', startByte = 25, endByte = 31)" "]" "], startByte = 0, endByte = 32)" "])", doLex("(foo bar, baz qux, corge grault)").cStr()); EXPECT_STREQ( "(tokens = [" "(parenthesizedList = [" "[" "(identifier = 'foo', startByte = 1, endByte = 4), " "(identifier = 'bar', startByte = 5, endByte = 8)" "]" "], startByte = 0, endByte = 9)" "])", doLex("(foo bar)").cStr()); // Empty parentheses should result in an empty list-of-lists, *not* a list containing an empty // list. EXPECT_STREQ( "(tokens = [" "(parenthesizedList = [], startByte = 0, endByte = 4)" "])", doLex("( )").cStr()); EXPECT_STREQ( "(tokens = [" "(bracketedList = [" "[" "(identifier = 'foo', startByte = 1, endByte = 4), " "(identifier = 'bar', startByte = 5, endByte = 8)" "], [" "(identifier = 'baz', startByte = 10, endByte = 13), " "(identifier = 'qux', startByte = 14, endByte = 17)" "], [" "(identifier = 'corge', startByte = 19, endByte = 24), " "(identifier = 'grault', startByte = 25, endByte = 31)" "]" "], startByte = 0, endByte = 32)" "])", doLex("[foo bar, baz qux, corge grault]").cStr()); // Trailing commas should not create an empty final list item, but be stripped by the lexer. EXPECT_STREQ( "(tokens = [" "(bracketedList = [" "[" "(identifier = 'foo', startByte = 1, endByte = 4)" "], [" "(identifier = 'bar', startByte = 6, endByte = 9)" "]" "], startByte = 0, endByte = 11)" "])", doLex("[foo, bar,]").cStr()); EXPECT_STREQ( "(tokens = [" "(bracketedList = [" "[" "(identifier = 'foo', startByte = 1, endByte = 4)" "], [" "(parenthesizedList = [" "[" "(identifier = 'bar', startByte = 7, endByte = 10)" "], [" "(identifier = 'baz', startByte = 12, endByte = 15)" "]" "], startByte = 6, endByte = 16)" "]" "], startByte = 0, endByte = 17), " "(identifier = 'qux', startByte = 18, endByte = 21)" "])", doLex("[foo, (bar, baz)] qux").cStr()); EXPECT_STREQ( "(tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3), " "(identifier = 'bar', startByte = 7, endByte = 10)" "])", doLex("foo\n\r\t\vbar").cStr()); } TEST(Lexer, Statements) { EXPECT_STREQ( "(statements = [" "(tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3), " "(identifier = 'bar', startByte = 4, endByte = 7)" "], line = void, startByte = 0, endByte = 8)" "])", doLex("foo bar;").cStr()); EXPECT_STREQ( "(statements = [" "(tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], line = void, startByte = 0, endByte = 4), " "(tokens = [" "(identifier = 'bar', startByte = 5, endByte = 8)" "], line = void, startByte = 5, endByte = 9), " "(tokens = [" "(identifier = 'baz', startByte = 10, endByte = 13)" "], line = void, startByte = 10, endByte = 14)" "])", doLex("foo; bar; baz; ").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "block = [" "(tokens = [" "(identifier = 'bar', startByte = 5, endByte = 8)" "], line = void, startByte = 5, endByte = 9), " "(tokens = [" "(identifier = 'baz', startByte = 10, endByte = 13)" "], line = void, startByte = 10, endByte = 14)" "], " "startByte = 0, endByte = 15" "), " "(tokens = [" "(identifier = 'qux', startByte = 16, endByte = 19)" "], line = void, startByte = 16, endByte = 20)" "])", doLex("foo {bar; baz;} qux;").cStr()); } TEST(Lexer, DocComments) { EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "docComment = 'blah blah\\n', " "startByte = 0, endByte = 16" ")" "])", doLex("foo; # blah blah").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "docComment = 'blah blah\\n', " "startByte = 0, endByte = 15" ")" "])", doLex("foo; #blah blah").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "docComment = ' blah blah\\n', " "startByte = 0, endByte = 17" ")" "])", doLex("foo; # blah blah").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "docComment = 'blah blah\\n', " "startByte = 0, endByte = 16" ")" "])", doLex("foo;\n# blah blah").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "startByte = 0, endByte = 4" ")" "])", doLex("foo;\n\n# blah blah").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "line = void, " "docComment = 'bar baz\\nqux corge\\n', " "startByte = 0, endByte = 30" ")" "])", doLex("foo;\n # bar baz\n # qux corge\n\n# grault\n# garply").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "block = [" "(tokens = [" "(identifier = 'bar', startByte = 17, endByte = 20)" "], line = void, docComment = 'hi\\n', startByte = 17, endByte = 27), " "(tokens = [" "(identifier = 'baz', startByte = 28, endByte = 31)" "], line = void, startByte = 28, endByte = 32)" "], " "docComment = 'blah blah\\n', " "startByte = 0, endByte = 44" "), " "(tokens = [" "(identifier = 'qux', startByte = 44, endByte = 47)" "], line = void, startByte = 44, endByte = 48)" "])", doLex("foo {# blah blah\nbar; # hi\n baz;} # ignored\nqux;").cStr()); EXPECT_STREQ( "(statements = [" "(" "tokens = [" "(identifier = 'foo', startByte = 0, endByte = 3)" "], " "block = [" "(tokens = [" "(identifier = 'bar', startByte = 5, endByte = 8)" "], line = void, startByte = 5, endByte = 9), " "(tokens = [" "(identifier = 'baz', startByte = 10, endByte = 13)" "], line = void, startByte = 10, endByte = 14)" "], " "docComment = 'late comment\\n', " "startByte = 0, endByte = 31" "), " "(tokens = [" "(identifier = 'qux', startByte = 31, endByte = 34)" "], line = void, startByte = 31, endByte = 35)" "])", doLex("foo {bar; baz;}\n# late comment\nqux;").cStr()); } TEST(Lexer, Utf8Bom) { EXPECT_STREQ( "(tokens = [" "(identifier = 'foo', startByte = 3, endByte = 6), " "(identifier = 'bar', startByte = 7, endByte = 10), " "(identifier = 'baz', startByte = 13, endByte = 16)" "])", doLex("\xef\xbb\xbf""foo bar\xef\xbb\xbf""baz").cStr()); } } // namespace } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/capnpc-capnp.c++0000644000175000017500000006654714712011043023314 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This program is a code generator plugin for `capnp compile` which writes the schema back to // stdout in roughly capnpc format. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include "../serialize.h" #include #include #include #include #include "../schema-loader.h" #include "../dynamic.h" #include #include #include #include #include #include #if HAVE_CONFIG_H #include "config.h" #endif #ifndef VERSION #define VERSION "(unknown)" #endif namespace capnp { namespace { bool hasDiscriminantValue(const schema::Field::Reader& reader) { return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; } struct Indent { uint amount; Indent() = default; inline Indent(int amount): amount(amount) {} Indent next() { return Indent(amount + 2); } struct Iterator { uint i; Iterator() = default; inline Iterator(uint i): i(i) {} inline char operator*() const { return ' '; } inline Iterator& operator++() { ++i; return *this; } inline Iterator operator++(int) { Iterator result = *this; ++i; return result; } inline bool operator==(const Iterator& other) const { return i == other.i; } inline bool operator!=(const Iterator& other) const { return i != other.i; } }; inline size_t size() const { return amount; } inline Iterator begin() const { return Iterator(0); } inline Iterator end() const { return Iterator(amount); } }; inline Indent KJ_STRINGIFY(const Indent& indent) { return indent; } // ======================================================================================= class CapnpcCapnpMain { public: CapnpcCapnpMain(kj::ProcessContext& context): context(context) {} kj::MainFunc getMain() { return kj::MainBuilder(context, "Cap'n Proto loopback plugin version " VERSION, "This is a Cap'n Proto compiler plugin which \"de-compiles\" the schema back into " "Cap'n Proto schema language format, with comments showing the offsets chosen by the " "compiler. This is meant to be run using the Cap'n Proto compiler, e.g.:\n" " capnp compile -ocapnp foo.capnp") .callAfterParsing(KJ_BIND_METHOD(*this, run)) .build(); } private: kj::ProcessContext& context; SchemaLoader schemaLoader; Text::Reader getUnqualifiedName(Schema schema) { auto proto = schema.getProto(); KJ_CONTEXT(proto.getDisplayName()); auto parent = schemaLoader.get(proto.getScopeId()); for (auto nested: parent.getProto().getNestedNodes()) { if (nested.getId() == proto.getId()) { return nested.getName(); } } KJ_FAIL_REQUIRE("A schema Node's supposed scope did not contain the node as a NestedNode."); return "(?)"; } kj::StringTree nodeName(Schema target, Schema scope, schema::Brand::Reader brand, kj::Maybe method) { kj::Vector targetPath; kj::Vector scopeParts; targetPath.add(target); std::map::Reader> scopeBindings; for (auto scopeBrand: brand.getScopes()) { switch (scopeBrand.which()) { case schema::Brand::Scope::BIND: scopeBindings[scopeBrand.getScopeId()] = scopeBrand.getBind(); break; case schema::Brand::Scope::INHERIT: // TODO(someday): We need to pay attention to INHERIT and be sure to explicitly override // any bindings that are not inherited. This requires a way to determine which of our // parent scopes have a non-empty parameter list. break; } } { Schema parent = target; while (parent.getProto().getScopeId() != 0) { parent = schemaLoader.get(parent.getProto().getScopeId()); targetPath.add(parent); } } { Schema parent = scope; scopeParts.add(parent); while (parent.getProto().getScopeId() != 0) { parent = schemaLoader.get(parent.getProto().getScopeId()); scopeParts.add(parent); } } // Remove common scope (unless it has been reparameterized). // TODO(someday): This is broken in that we aren't checking for shadowing. while (!scopeParts.empty() && targetPath.size() > 1 && scopeParts.back() == targetPath.back() && scopeBindings.count(scopeParts.back().getProto().getId()) == 0) { scopeParts.removeLast(); targetPath.removeLast(); } auto parts = kj::heapArrayBuilder(targetPath.size()); while (!targetPath.empty()) { auto part = targetPath.back(); auto proto = part.getProto(); kj::StringTree partStr; if (proto.getScopeId() == 0) { partStr = kj::strTree("import \"/", proto.getDisplayName(), '\"'); } else { partStr = kj::strTree(getUnqualifiedName(part)); } auto iter = scopeBindings.find(proto.getId()); if (iter != scopeBindings.end()) { auto bindings = KJ_MAP(binding, iter->second) { switch (binding.which()) { case schema::Brand::Binding::UNBOUND: return kj::strTree("AnyPointer"); case schema::Brand::Binding::TYPE: return genType(binding.getType(), scope, method); } return kj::strTree(""); }; partStr = kj::strTree(kj::mv(partStr), "(", kj::StringTree(kj::mv(bindings), ", "), ")"); } parts.add(kj::mv(partStr)); targetPath.removeLast(); } return kj::StringTree(parts.finish(), "."); } kj::StringTree genType(schema::Type::Reader type, Schema scope, kj::Maybe method) { switch (type.which()) { case schema::Type::VOID: return kj::strTree("Void"); case schema::Type::BOOL: return kj::strTree("Bool"); case schema::Type::INT8: return kj::strTree("Int8"); case schema::Type::INT16: return kj::strTree("Int16"); case schema::Type::INT32: return kj::strTree("Int32"); case schema::Type::INT64: return kj::strTree("Int64"); case schema::Type::UINT8: return kj::strTree("UInt8"); case schema::Type::UINT16: return kj::strTree("UInt16"); case schema::Type::UINT32: return kj::strTree("UInt32"); case schema::Type::UINT64: return kj::strTree("UInt64"); case schema::Type::FLOAT32: return kj::strTree("Float32"); case schema::Type::FLOAT64: return kj::strTree("Float64"); case schema::Type::TEXT: return kj::strTree("Text"); case schema::Type::DATA: return kj::strTree("Data"); case schema::Type::LIST: return kj::strTree("List(", genType(type.getList().getElementType(), scope, method), ")"); case schema::Type::ENUM: return nodeName(schemaLoader.get(type.getEnum().getTypeId()), scope, type.getEnum().getBrand(), method); case schema::Type::STRUCT: return nodeName(schemaLoader.get(type.getStruct().getTypeId()), scope, type.getStruct().getBrand(), method); case schema::Type::INTERFACE: return nodeName(schemaLoader.get(type.getInterface().getTypeId()), scope, type.getInterface().getBrand(), method); case schema::Type::ANY_POINTER: { auto anyPointer = type.getAnyPointer(); switch (anyPointer.which()) { case schema::Type::AnyPointer::UNCONSTRAINED: switch (anyPointer.getUnconstrained().which()) { case schema::Type::AnyPointer::Unconstrained::ANY_KIND: return kj::strTree("AnyPointer"); case schema::Type::AnyPointer::Unconstrained::STRUCT: return kj::strTree("AnyStruct"); case schema::Type::AnyPointer::Unconstrained::LIST: return kj::strTree("AnyList"); case schema::Type::AnyPointer::Unconstrained::CAPABILITY: return kj::strTree("Capability"); } KJ_UNREACHABLE; case schema::Type::AnyPointer::PARAMETER: { auto param = anyPointer.getParameter(); auto scopeProto = scope.getProto(); auto targetScopeId = param.getScopeId(); while (scopeProto.getId() != targetScopeId) { scopeProto = schemaLoader.get(param.getScopeId()).getProto(); } auto params = scopeProto.getParameters(); KJ_REQUIRE(param.getParameterIndex() < params.size()); return kj::strTree(params[param.getParameterIndex()].getName()); } case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: { auto params = KJ_REQUIRE_NONNULL(method).getProto().getImplicitParameters(); uint index = anyPointer.getImplicitMethodParameter().getParameterIndex(); KJ_REQUIRE(index < params.size()); return kj::strTree(params[index].getName()); } } KJ_UNREACHABLE; } } return kj::strTree(); } int typeSizeBits(schema::Type::Reader type) { switch (type.which()) { case schema::Type::VOID: return 0; case schema::Type::BOOL: return 1; case schema::Type::INT8: return 8; case schema::Type::INT16: return 16; case schema::Type::INT32: return 32; case schema::Type::INT64: return 64; case schema::Type::UINT8: return 8; case schema::Type::UINT16: return 16; case schema::Type::UINT32: return 32; case schema::Type::UINT64: return 64; case schema::Type::FLOAT32: return 32; case schema::Type::FLOAT64: return 64; case schema::Type::TEXT: return -1; case schema::Type::DATA: return -1; case schema::Type::LIST: return -1; case schema::Type::ENUM: return 16; case schema::Type::STRUCT: return -1; case schema::Type::INTERFACE: return -1; case schema::Type::ANY_POINTER: return -1; } return 0; } bool isEmptyValue(schema::Value::Reader value) { switch (value.which()) { case schema::Value::VOID: return true; case schema::Value::BOOL: return value.getBool() == false; case schema::Value::INT8: return value.getInt8() == 0; case schema::Value::INT16: return value.getInt16() == 0; case schema::Value::INT32: return value.getInt32() == 0; case schema::Value::INT64: return value.getInt64() == 0; case schema::Value::UINT8: return value.getUint8() == 0; case schema::Value::UINT16: return value.getUint16() == 0; case schema::Value::UINT32: return value.getUint32() == 0; case schema::Value::UINT64: return value.getUint64() == 0; case schema::Value::FLOAT32: return value.getFloat32() == 0; case schema::Value::FLOAT64: return value.getFloat64() == 0; case schema::Value::TEXT: return !value.hasText(); case schema::Value::DATA: return !value.hasData(); case schema::Value::LIST: return !value.hasList(); case schema::Value::ENUM: return value.getEnum() == 0; case schema::Value::STRUCT: return !value.hasStruct(); case schema::Value::INTERFACE: return true; case schema::Value::ANY_POINTER: return true; } return true; } kj::StringTree genValue(Type type, schema::Value::Reader value) { switch (value.which()) { case schema::Value::VOID: return kj::strTree("void"); case schema::Value::BOOL: return kj::strTree(value.getBool() ? "true" : "false"); case schema::Value::INT8: return kj::strTree((int)value.getInt8()); case schema::Value::INT16: return kj::strTree(value.getInt16()); case schema::Value::INT32: return kj::strTree(value.getInt32()); case schema::Value::INT64: return kj::strTree(value.getInt64()); case schema::Value::UINT8: return kj::strTree((uint)value.getUint8()); case schema::Value::UINT16: return kj::strTree(value.getUint16()); case schema::Value::UINT32: return kj::strTree(value.getUint32()); case schema::Value::UINT64: return kj::strTree(value.getUint64()); case schema::Value::FLOAT32: return kj::strTree(value.getFloat32()); case schema::Value::FLOAT64: return kj::strTree(value.getFloat64()); case schema::Value::TEXT: return kj::strTree(DynamicValue::Reader(value.getText())); case schema::Value::DATA: return kj::strTree(DynamicValue::Reader(value.getData())); case schema::Value::LIST: { auto listValue = value.getList().getAs(type.asList()); return kj::strTree(listValue); } case schema::Value::ENUM: { auto enumNode = type.asEnum().getProto(); auto enumerants = enumNode.getEnum().getEnumerants(); KJ_REQUIRE(value.getEnum() < enumerants.size(), "Enum value out-of-range.", value.getEnum(), enumNode.getDisplayName()); return kj::strTree(enumerants[value.getEnum()].getName()); } case schema::Value::STRUCT: { KJ_REQUIRE(type.which() == schema::Type::STRUCT, "type/value mismatch"); auto structValue = value.getStruct().getAs(type.asStruct()); return kj::strTree(structValue); } case schema::Value::INTERFACE: { return kj::strTree(""); } case schema::Value::ANY_POINTER: { return kj::strTree(""); } } return kj::strTree(""); } kj::StringTree genGenericParams(List::Reader params, Schema scope) { if (params.size() == 0) { return kj::strTree(); } return kj::strTree(" (", kj::StringTree( KJ_MAP(param, params) { return kj::strTree(param.getName()); }, ", "), ')'); } kj::StringTree genGenericParams(Schema schema) { auto proto = schema.getProto(); return genGenericParams(proto.getParameters(), schemaLoader.get(proto.getScopeId())); } kj::StringTree genAnnotation(schema::Annotation::Reader annotation, Schema scope, const char* prefix = " ", const char* suffix = "") { auto decl = schemaLoader.get(annotation.getId(), annotation.getBrand(), scope); auto proto = decl.getProto(); KJ_REQUIRE(proto.isAnnotation()); auto annDecl = proto.getAnnotation(); auto value = genValue(schemaLoader.getType(annDecl.getType(), decl), annotation.getValue()).flatten(); if (value.startsWith("(")) { return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand(), nullptr), value, suffix); } else { return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand(), nullptr), "(", value, ")", suffix); } } kj::StringTree genAnnotations(List::Reader list, Schema scope) { return kj::strTree(KJ_MAP(ann, list) { return genAnnotation(ann, scope); }); } kj::StringTree genAnnotations(Schema schema) { auto proto = schema.getProto(); return genAnnotations(proto.getAnnotations(), schemaLoader.get(proto.getScopeId())); } const char* elementSizeName(schema::ElementSize size) { switch (size) { case schema::ElementSize::EMPTY: return "void"; case schema::ElementSize::BIT: return "1-bit"; case schema::ElementSize::BYTE: return "8-bit"; case schema::ElementSize::TWO_BYTES: return "16-bit"; case schema::ElementSize::FOUR_BYTES: return "32-bit"; case schema::ElementSize::EIGHT_BYTES: return "64-bit"; case schema::ElementSize::POINTER: return "pointer"; case schema::ElementSize::INLINE_COMPOSITE: return "inline composite"; } return ""; } struct OrderByCodeOrder { template inline bool operator()(const T& a, const T& b) const { return a.getProto().getCodeOrder() < b.getProto().getCodeOrder(); } }; template kj::Array()[0])> sortByCodeOrder(MemberList&& list) { auto sorted = KJ_MAP(item, list) { return item; }; std::sort(sorted.begin(), sorted.end(), OrderByCodeOrder()); return kj::mv(sorted); } kj::Array genStructFields(StructSchema schema, Indent indent) { // Slightly hacky: We want to print in code order, but we also need to print the union in one // chunk. Its fields should be together in code order anyway, but it's easier to simply // output the whole union in place of the first union field, and then output nothing for the // subsequent fields. bool seenUnion = false; return KJ_MAP(field, sortByCodeOrder(schema.getFields())) { if (hasDiscriminantValue(field.getProto())) { if (seenUnion) { return kj::strTree(); } else { seenUnion = true; uint offset = schema.getProto().getStruct().getDiscriminantOffset(); // GCC 4.7.3 crashes if you inline unionFields. auto unionFields = sortByCodeOrder(schema.getUnionFields()); return kj::strTree( indent, "union { # tag bits [", offset * 16, ", ", offset * 16 + 16, ")\n", KJ_MAP(uField, unionFields) { return genStructField(uField, schema, indent.next()); }, indent, "}\n"); } } else { return genStructField(field, schema, indent); } }; } kj::StringTree genStructField(StructSchema::Field field, Schema scope, Indent indent) { auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); int size = typeSizeBits(slot.getType()); return kj::strTree( indent, proto.getName(), " @", proto.getOrdinal().getExplicit(), " :", genType(slot.getType(), scope, nullptr), isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") : kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())), genAnnotations(proto.getAnnotations(), scope), "; # ", size == -1 ? kj::strTree("ptr[", slot.getOffset(), "]") : kj::strTree("bits[", slot.getOffset() * size, ", ", (slot.getOffset() + 1) * size, ")"), hasDiscriminantValue(proto) ? kj::strTree(", union tag = ", proto.getDiscriminantValue()) : kj::strTree(), "\n"); } case schema::Field::GROUP: { auto group = field.getType().asStruct(); return kj::strTree( indent, proto.getName(), " :group", genAnnotations(proto.getAnnotations(), scope), " {", hasDiscriminantValue(proto) ? kj::strTree(" # union tag = ", proto.getDiscriminantValue()) : kj::strTree(), "\n", genStructFields(group, indent.next()), indent, "}\n"); } } return kj::strTree(); } kj::StringTree genParamList(InterfaceSchema interface, StructSchema schema, schema::Brand::Reader brand, InterfaceSchema::Method method) { if (schema.getProto().getId() == typeId()) { return kj::strTree("stream"); } else if (schema.getProto().getScopeId() == 0) { // A named parameter list. return kj::strTree("(", kj::StringTree( KJ_MAP(field, schema.getFields()) { auto proto = field.getProto(); auto slot = proto.getSlot(); return kj::strTree( proto.getName(), " :", genType(slot.getType(), interface, nullptr), isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") : kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())), genAnnotations(proto.getAnnotations(), interface)); }, ", "), ")"); } else { return nodeName(schema, interface, brand, method); } } kj::StringTree genSuperclasses(InterfaceSchema interface) { auto superclasses = interface.getProto().getInterface().getSuperclasses(); if (superclasses.size() == 0) { return kj::strTree(); } else { return kj::strTree(" superclasses(", kj::StringTree( KJ_MAP(superclass, superclasses) { return nodeName(schemaLoader.get(superclass.getId()), interface, superclass.getBrand(), nullptr); }, ", "), ")"); } } kj::StringTree genDecl(Schema schema, Text::Reader name, uint64_t scopeId, Indent indent) { auto proto = schema.getProto(); if (proto.getScopeId() != scopeId) { // This appears to be an alias for something declared elsewhere. KJ_FAIL_REQUIRE("Aliases not implemented."); } switch (proto.which()) { case schema::Node::FILE: KJ_FAIL_REQUIRE("Encountered nested file node."); break; case schema::Node::STRUCT: { auto structProto = proto.getStruct(); return kj::strTree( indent, "struct ", name, " @0x", kj::hex(proto.getId()), genGenericParams(schema), genAnnotations(schema), " { # ", structProto.getDataWordCount() * 8, " bytes, ", structProto.getPointerCount(), " ptrs", structProto.getPreferredListEncoding() == schema::ElementSize::INLINE_COMPOSITE ? kj::strTree() : kj::strTree(", packed as ", elementSizeName(structProto.getPreferredListEncoding())), "\n", genStructFields(schema.asStruct(), indent.next()), genNestedDecls(schema, indent.next()), indent, "}\n"); } case schema::Node::ENUM: { return kj::strTree( indent, "enum ", name, " @0x", kj::hex(proto.getId()), genAnnotations(schema), " {\n", KJ_MAP(enumerant, sortByCodeOrder(schema.asEnum().getEnumerants())) { return kj::strTree(indent.next(), enumerant.getProto().getName(), " @", enumerant.getIndex(), genAnnotations(enumerant.getProto().getAnnotations(), schema), ";\n"); }, genNestedDecls(schema, indent.next()), indent, "}\n"); } case schema::Node::INTERFACE: { auto interface = schema.asInterface(); return kj::strTree( indent, "interface ", name, " @0x", kj::hex(proto.getId()), genGenericParams(schema), genSuperclasses(interface), genAnnotations(schema), " {\n", KJ_MAP(method, sortByCodeOrder(interface.getMethods())) { auto methodProto = method.getProto(); auto implicits = methodProto.getImplicitParameters(); kj::StringTree implicitsStr; if (implicits.size() > 0) { implicitsStr = kj::strTree( "[", kj::StringTree(KJ_MAP(implicit, implicits) { return kj::strTree(implicit.getName()); }, ", "), "] "); } auto params = schemaLoader.get(methodProto.getParamStructType()).asStruct(); auto results = schemaLoader.get(methodProto.getResultStructType()).asStruct(); return kj::strTree( indent.next(), methodProto.getName(), " @", method.getIndex(), " ", kj::mv(implicitsStr), genParamList(interface, params, methodProto.getParamBrand(), method), " -> ", genParamList(interface, results, methodProto.getResultBrand(), method), genAnnotations(methodProto.getAnnotations(), interface), ";\n"); }, genNestedDecls(schema, indent.next()), indent, "}\n"); } case schema::Node::CONST: { auto constProto = proto.getConst(); return kj::strTree( indent, "const ", name, " @0x", kj::hex(proto.getId()), " :", genType(constProto.getType(), schema, nullptr), " = ", genValue(schema.asConst().getType(), constProto.getValue()), genAnnotations(schema), ";\n"); } case schema::Node::ANNOTATION: { auto annotationProto = proto.getAnnotation(); kj::Vector targets(8); bool targetsAll = true; auto dynamic = toDynamic(annotationProto); for (auto field: dynamic.getSchema().getFields()) { auto fieldName = field.getProto().getName(); if (fieldName.startsWith("targets")) { if (dynamic.get(field).as()) { auto target = kj::str(fieldName.slice(strlen("targets"))); target[0] = target[0] - 'A' + 'a'; targets.add(kj::mv(target)); } else { targetsAll = false; } } } if (targetsAll) { targets = kj::Vector(1); targets.add(kj::heapString("*")); } return kj::strTree( indent, "annotation ", name, " @0x", kj::hex(proto.getId()), " (", strArray(targets, ", "), ") :", genType(annotationProto.getType(), schema, nullptr), genAnnotations(schema), ";\n"); } } return kj::strTree(); } kj::StringTree genNestedDecls(Schema schema, Indent indent) { uint64_t id = schema.getProto().getId(); return kj::strTree(KJ_MAP(nested, schema.getProto().getNestedNodes()) { return genDecl(schemaLoader.get(nested.getId()), nested.getName(), id, indent); }); } kj::StringTree genFile(Schema file) { auto proto = file.getProto(); KJ_REQUIRE(proto.isFile(), "Expected a file node.", (uint)proto.which()); return kj::strTree( "# ", proto.getDisplayName(), "\n", "@0x", kj::hex(proto.getId()), ";\n", KJ_MAP(ann, proto.getAnnotations()) { return genAnnotation(ann, file, "", ";\n"); }, genNestedDecls(file, Indent(0))); } kj::MainBuilder::Validity run() { ReaderOptions options; options.traversalLimitInWords = 1 << 30; // Don't limit. StreamFdMessageReader reader(STDIN_FILENO, options); auto request = reader.getRoot(); for (auto node: request.getNodes()) { schemaLoader.load(node); } kj::FdOutputStream rawOut(STDOUT_FILENO); kj::BufferedOutputStreamWrapper out(rawOut); for (auto requestedFile: request.getRequestedFiles()) { genFile(schemaLoader.get(requestedFile.getId())).visit( [&](kj::ArrayPtr text) { out.write(text.begin(), text.size()); }); } return true; } }; } // namespace } // namespace capnp KJ_MAIN(capnp::CapnpcCapnpMain); capnproto-c++-1.1.0/src/capnp/compiler/error-reporter.c++0000644000175000017500000000435314527152321023736 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "error-reporter.h" #include namespace capnp { namespace compiler { namespace { template static size_t findLargestElementBefore(const kj::Vector& vec, const T& key) { KJ_REQUIRE(vec.size() > 0 && vec[0] <= key); size_t lower = 0; size_t upper = vec.size(); while (upper - lower > 1) { size_t mid = (lower + upper) / 2; if (vec[mid] > key) { upper = mid; } else { lower = mid; } } return lower; } } // namespace LineBreakTable::LineBreakTable(kj::ArrayPtr content) : lineBreaks(content.size() / 40) { lineBreaks.add(0); for (const char* pos = content.begin(); pos < content.end(); ++pos) { if (*pos == '\n') { lineBreaks.add(pos + 1 - content.begin()); } } } GlobalErrorReporter::SourcePos LineBreakTable::toSourcePos(uint32_t byteOffset) const { uint line = findLargestElementBefore(lineBreaks, byteOffset); uint col = byteOffset - lineBreaks[line]; return GlobalErrorReporter::SourcePos { byteOffset, line, col }; } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/node-translator.h0000644000175000017500000002347414712011043023734 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include #include #include #include "error-reporter.h" #include "resolver.h" #include "generics.h" #include CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { class NodeTranslator { // Translates one node in the schema from AST form to final schema form. A "node" is anything // that has a unique ID, such as structs, enums, constants, and annotations, but not fields, // unions, enumerants, or methods (the latter set have 16-bit ordinals but not 64-bit global IDs). public: NodeTranslator(Resolver& resolver, ErrorReporter& errorReporter, const Declaration::Reader& decl, Orphan wipNode, bool compileAnnotations); // Construct a NodeTranslator to translate the given declaration. The wipNode starts out with // `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized. The `NodeTranslator` // fills in the rest. ~NodeTranslator() noexcept(false); struct NodeSet { schema::Node::Reader node; // The main node. kj::Array auxNodes; // Auxiliary nodes that were produced when translating this node and should be loaded along // with it. In particular, structs that contain groups (or named unions) spawn extra nodes // representing those, and interfaces spawn struct nodes representing method params/results. kj::Array sourceInfo; // The SourceInfo for the node and all aux nodes. }; NodeSet getBootstrapNode(); // Get an incomplete version of the node in which pointer-typed value expressions have not yet // been translated. Instead, for all `schema.Value` objects representing pointer-type values, // the value is set to an appropriate "empty" value. This version of the schema can be used to // bootstrap the dynamic API which can then in turn be used to encode the missing complex values. // // If the final node has already been built, this will actually return the final node (in fact, // it's the same node object). NodeSet finish(Schema selfUnboundBootstrap); // Finish translating the node (including filling in all the pieces that are missing from the // bootstrap node) and return it. // // `selfUnboundBootstrap` is a Schema build using the Node returned by getBootstrapNode(), and // with generic parameters "unbound", i.e. it was returned by SchemaLoader::getUnbound(). static kj::Maybe compileDecl( uint64_t scopeId, uint scopeParameterCount, Resolver& resolver, ErrorReporter& errorReporter, Expression::Reader expression, schema::Brand::Builder brandBuilder); // Compile a one-off declaration expression without building a NodeTranslator. Used for // evaluating aliases. // // `brandBuilder` may be used to construct a message which will fill in ResolvedDecl::brand in // the result. private: class DuplicateNameDetector; class DuplicateOrdinalDetector; class StructLayout; class StructTranslator; Resolver& resolver; ErrorReporter& errorReporter; Orphanage orphanage; bool compileAnnotations; kj::Own localBrand; Orphan wipNode; // The work-in-progress schema node. Orphan sourceInfo; // Doc comments and other source info for this node. struct AuxNode { Orphan node; Orphan sourceInfo; }; kj::Vector groups; // If this is a struct node and it contains groups, these are the nodes for those groups, which // must be loaded together with the top-level node. kj::Vector paramStructs; // If this is an interface, these are the auto-generated structs representing params and results. struct UnfinishedValue { Expression::Reader source; schema::Type::Reader type; kj::Maybe typeScope; schema::Value::Builder target; }; kj::Vector unfinishedValues; // List of values in `wipNode` which have not yet been interpreted, because they are structs // or lists and as such interpreting them require using the types' schemas (to take advantage // of the dynamic API). Once bootstrap schemas have been built, they can be used to interpret // these values. void compileNode(Declaration::Reader decl, schema::Node::Builder builder); void compileConst(Declaration::Const::Reader decl, schema::Node::Const::Builder builder); void compileAnnotation(Declaration::Annotation::Reader decl, schema::Node::Annotation::Builder builder); void compileEnum(Void decl, List::Reader members, schema::Node::Builder builder); void compileStruct(Void decl, List::Reader members, schema::Node::Builder builder); void compileInterface(Declaration::Interface::Reader decl, List::Reader members, schema::Node::Builder builder); // The `members` arrays contain only members with ordinal numbers, in code order. Other members // are handled elsewhere. template uint64_t compileParamList(kj::StringPtr methodName, uint16_t ordinal, bool isResults, Declaration::ParamList::Reader paramList, typename List::Reader implicitParams, InitBrandFunc&& initBrand); // Compile a param (or result) list and return the type ID of the struct type. kj::Maybe compileDeclExpression( Expression::Reader source, ImplicitParams implicitMethodParams); // Compile an expression which is expected to resolve to a declaration or type expression. bool compileType(Expression::Reader source, schema::Type::Builder target, ImplicitParams implicitMethodParams); // Returns false if there was a problem, in which case value expressions of this type should // not be parsed. void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target); // Initializes `target` to contain the "default default" value for `type`. void compileBootstrapValue( Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target, kj::Maybe typeScope = nullptr); // Calls compileValue() if this value should be interpreted at bootstrap time. Otherwise, // adds the value to `unfinishedValues` for later evaluation. // // If `type` comes from some other node, `typeScope` is the schema for that node. Otherwise the // scope of the type expression is assumed to be this node (meaning, in particular, that no // generic type parameters are bound). void compileValue(Expression::Reader source, schema::Type::Reader type, Schema typeScope, schema::Value::Builder target, bool isBootstrap); // Interprets the value expression and initializes `target` with the result. kj::Maybe readConstant(Expression::Reader name, bool isBootstrap); // Get the value of the given constant. May return null if some error occurs, which will already // have been reported. kj::Maybe> readEmbed(LocatedText::Reader filename); // Read a raw file for embedding. Orphan> compileAnnotationApplications( List::Reader annotations, kj::StringPtr targetsFlagName); }; class ValueTranslator { public: class Resolver { public: virtual kj::Maybe resolveConstant(Expression::Reader name) = 0; virtual kj::Maybe> readEmbed(LocatedText::Reader filename) = 0; }; ValueTranslator(Resolver& resolver, ErrorReporter& errorReporter, Orphanage orphanage) : resolver(resolver), errorReporter(errorReporter), orphanage(orphanage) {} kj::Maybe> compileValue(Expression::Reader src, Type type); void fillStructValue(DynamicStruct::Builder builder, List::Reader assignments); // Interprets the given assignments and uses them to fill in the given struct builder. private: Resolver& resolver; ErrorReporter& errorReporter; Orphanage orphanage; Orphan compileValueInner(Expression::Reader src, Type type); bool matchesType(Expression::Reader src, Type type, Orphan& result); // Helpers for compileValue(). kj::String makeNodeName(Schema node); kj::String makeTypeName(Type type); kj::Maybe makeListSchemaOf(schema::Type::Reader elementType); }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/module-loader.c++0000644000175000017500000002552114731420004023467 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "module-loader.h" #include "lexer.h" #include "parser.h" #include #include #include #include #include #include namespace capnp { namespace compiler { namespace { struct FileKey { // Key type for the modules map. We need to implement some complicated heuristics to detect when // two files are actually the same underlying file on disk, in order to handle the case where // people have mapped the same file into multiple locations in the import tree, whether by // passing overlapping import paths, weird symlinks, or whatever. // // This is probably over-engineered. const kj::ReadableDirectory& baseDir; kj::PathPtr path; kj::Maybe file; uint64_t hashCode; uint64_t size; kj::Date lastModified; FileKey(const kj::ReadableDirectory& baseDir, kj::PathPtr path) : baseDir(baseDir), path(path), file(nullptr), hashCode(0), size(0), lastModified(kj::UNIX_EPOCH) {} FileKey(const kj::ReadableDirectory& baseDir, kj::PathPtr path, const kj::ReadableFile& file) : FileKey(baseDir, path, file, file.stat()) {} FileKey(const kj::ReadableDirectory& baseDir, kj::PathPtr path, const kj::ReadableFile& file, kj::FsNode::Metadata meta) : baseDir(baseDir), path(path), file(&file), hashCode(meta.hashCode), size(meta.size), lastModified(meta.lastModified) {} bool operator==(const FileKey& other) const { // Allow matching on baseDir and path without a file. if (&baseDir == &other.baseDir && path == other.path) return true; if (file == nullptr || other.file == nullptr) return false; // Try comparing various file metadata to rule out obvious differences. if (hashCode != other.hashCode) return false; if (size != other.size || lastModified != other.lastModified) return false; if (path.size() > 0 && other.path.size() > 0 && path[path.size() - 1] != other.path[other.path.size() - 1]) { // Names differ, so probably not the same file. return false; } // Same file hash, but different paths, but same size and modification date. This could be a // case of two different import paths overlapping and containing the same file. We'll need to // check the content. auto mapping1 = KJ_ASSERT_NONNULL(file).mmap(0, size); auto mapping2 = KJ_ASSERT_NONNULL(other.file).mmap(0, size); if (memcmp(mapping1.begin(), mapping2.begin(), size) != 0) return false; if (path == other.path) { // Exactly the same content was mapped at exactly the same path relative to two different // import directories. This can only really happen if this was one of the files passed on // the command line, but its --src-prefix is not also an import path, but some other // directory containing the same file was given as an import path. Whatever, we'll ignore // this. return true; } // Exactly the same content! static bool warned = false; if (!warned) { KJ_LOG(WARNING, "Found exactly the same source file mapped at two different paths. This suggests " "that your -I and --src-prefix flags are overlapping or inconsistent. Remember, these " "flags should only specify directories that are logical 'roots' of the source tree. " "It should never be the case that one of the import directories contains another one of " "them.", path, other.path); warned = true; } return true; } }; struct FileKeyHash { size_t operator()(const FileKey& key) const { if (sizeof(size_t) < sizeof(key.hashCode)) { // 32-bit system, do more mixing return (key.hashCode >> 32) * 31 + static_cast(key.hashCode) + key.size * 103 + (key.lastModified - kj::UNIX_EPOCH) / kj::MILLISECONDS * 73; } else { return key.hashCode + key.size * 103 + (key.lastModified - kj::UNIX_EPOCH) / kj::NANOSECONDS * 73ull; } } }; }; class ModuleLoader::Impl { public: Impl(GlobalErrorReporter& errorReporter) : errorReporter(errorReporter) {} void addImportPath(const kj::ReadableDirectory& dir) { searchPath.add(&dir); } kj::Maybe loadModule(const kj::ReadableDirectory& dir, kj::PathPtr path); kj::Maybe loadModuleFromSearchPath(kj::PathPtr path); kj::Maybe> readEmbed(const kj::ReadableDirectory& dir, kj::PathPtr path); kj::Maybe> readEmbedFromSearchPath(kj::PathPtr path); GlobalErrorReporter& getErrorReporter() { return errorReporter; } void setFileIdsRequired(bool value) { fileIdsRequired = value; } bool areFileIdsRequired() { return fileIdsRequired; } private: GlobalErrorReporter& errorReporter; kj::Vector searchPath; std::unordered_map, FileKeyHash> modules; bool fileIdsRequired = true; }; class ModuleLoader::ModuleImpl final: public Module { public: ModuleImpl(ModuleLoader::Impl& loader, kj::Own file, const kj::ReadableDirectory& sourceDir, kj::Path pathParam) : loader(loader), file(kj::mv(file)), sourceDir(sourceDir), path(kj::mv(pathParam)), sourceNameStr(path.toString()) { KJ_REQUIRE(path.size() > 0); } kj::PathPtr getPath() { return path; } kj::StringPtr getSourceName() override { return sourceNameStr; } Orphan loadContent(Orphanage orphanage) override { kj::Array content = file->mmap(0, file->stat().size).releaseAsChars(); lineBreaks = nullptr; // In case loadContent() is called multiple times. lineBreaks = lineBreaksSpace.construct(content); MallocMessageBuilder lexedBuilder; auto statements = lexedBuilder.initRoot(); lex(content, statements, *this); auto parsed = orphanage.newOrphan(); parseFile(statements.getStatements(), parsed.get(), *this, loader.areFileIdsRequired()); return parsed; } kj::Maybe importRelative(kj::StringPtr importPath) override { if (importPath.size() > 0 && importPath[0] == '/') { return loader.loadModuleFromSearchPath(kj::Path::parse(importPath.slice(1))); } else { return loader.loadModule(sourceDir, path.parent().eval(importPath)); } } kj::Maybe> embedRelative(kj::StringPtr embedPath) override { if (embedPath.size() > 0 && embedPath[0] == '/') { return loader.readEmbedFromSearchPath(kj::Path::parse(embedPath.slice(1))); } else { return loader.readEmbed(sourceDir, path.parent().eval(embedPath)); } } void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { auto& lines = *KJ_REQUIRE_NONNULL(lineBreaks, "Can't report errors until loadContent() is called."); loader.getErrorReporter().addError(sourceDir, path, lines.toSourcePos(startByte), lines.toSourcePos(endByte), message); } bool hadErrors() override { return loader.getErrorReporter().hadErrors(); } void reportResolution(Resolution resolution) override{ resolutions.add(resolution); } kj::ArrayPtr getResolutions() override { return resolutions.asPtr(); } private: ModuleLoader::Impl& loader; kj::Own file; const kj::ReadableDirectory& sourceDir; kj::Path path; kj::String sourceNameStr; kj::SpaceFor lineBreaksSpace; kj::Maybe> lineBreaks; kj::Vector resolutions; }; // ======================================================================================= kj::Maybe ModuleLoader::Impl::loadModule( const kj::ReadableDirectory& dir, kj::PathPtr path) { auto iter = modules.find(FileKey(dir, path)); if (iter != modules.end()) { // Return existing file. return *iter->second; } KJ_IF_MAYBE(file, dir.tryOpenFile(path)) { auto pathCopy = path.clone(); auto key = FileKey(dir, pathCopy, **file); auto module = kj::heap(*this, kj::mv(*file), dir, kj::mv(pathCopy)); auto& result = *module; auto insertResult = modules.insert(std::make_pair(key, kj::mv(module))); if (insertResult.second) { return result; } else { // Now that we have the file open, we noticed a collision. Return the old file. return *insertResult.first->second; } } else { // No such file. return nullptr; } } kj::Maybe ModuleLoader::Impl::loadModuleFromSearchPath(kj::PathPtr path) { for (auto candidate: searchPath) { KJ_IF_MAYBE(module, loadModule(*candidate, path)) { return *module; } } return nullptr; } kj::Maybe> ModuleLoader::Impl::readEmbed( const kj::ReadableDirectory& dir, kj::PathPtr path) { KJ_IF_MAYBE(file, dir.tryOpenFile(path)) { return file->get()->mmap(0, file->get()->stat().size); } return nullptr; } kj::Maybe> ModuleLoader::Impl::readEmbedFromSearchPath(kj::PathPtr path) { for (auto candidate: searchPath) { KJ_IF_MAYBE(module, readEmbed(*candidate, path)) { return kj::mv(*module); } } return nullptr; } // ======================================================================================= ModuleLoader::ModuleLoader(GlobalErrorReporter& errorReporter) : impl(kj::heap(errorReporter)) {} ModuleLoader::~ModuleLoader() noexcept(false) {} void ModuleLoader::addImportPath(const kj::ReadableDirectory& dir) { impl->addImportPath(dir); } kj::Maybe ModuleLoader::loadModule(const kj::ReadableDirectory& dir, kj::PathPtr path) { return impl->loadModule(dir, path); } void ModuleLoader::setFileIdsRequired(bool value) { return impl->setFileIdsRequired(value); } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/type-id.c++0000644000175000017500000003252114712011043022305 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "type-id.h" #include #include namespace capnp { namespace compiler { class TypeIdGenerator { // A non-cryptographic deterministic random number generator used to generate type IDs when the // developer did not specify one themselves. // // The underlying algorithm is MD5. MD5 is safe to use here because this is not intended to be a // cryptographic random number generator. In retrospect it would have been nice to use something // else just to avoid people freaking out about it, but changing the algorithm now would break // backwards-compatibility. public: TypeIdGenerator(); void update(kj::ArrayPtr data); inline void update(kj::ArrayPtr data) { return update(data.asBytes()); } inline void update(kj::StringPtr data) { return update(data.asArray()); } kj::ArrayPtr finish(); private: bool finished = false; struct { uint lo, hi; uint a, b, c, d; kj::byte buffer[64]; uint block[16]; } ctx; const kj::byte* body(const kj::byte* ptr, size_t size); }; uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) { // Compute ID by hashing the concatenation of the parent ID and the declaration name, and // then taking the first 8 bytes. kj::byte parentIdBytes[sizeof(uint64_t)]; for (uint i = 0; i < sizeof(uint64_t); i++) { parentIdBytes[i] = (parentId >> (i * 8)) & 0xff; } TypeIdGenerator generator; generator.update(kj::arrayPtr(parentIdBytes, kj::size(parentIdBytes))); generator.update(childName); kj::ArrayPtr resultBytes = generator.finish(); uint64_t result = 0; for (uint i = 0; i < sizeof(uint64_t); i++) { result = (result << 8) | resultBytes[i]; } return result | (1ull << 63); } uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex) { // Compute ID by hashing the concatenation of the parent ID and the group index, and // then taking the first 8 bytes. kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t)]; for (uint i = 0; i < sizeof(uint64_t); i++) { bytes[i] = (parentId >> (i * 8)) & 0xff; } for (uint i = 0; i < sizeof(uint16_t); i++) { bytes[sizeof(uint64_t) + i] = (groupIndex >> (i * 8)) & 0xff; } TypeIdGenerator generator; generator.update(bytes); kj::ArrayPtr resultBytes = generator.finish(); uint64_t result = 0; for (uint i = 0; i < sizeof(uint64_t); i++) { result = (result << 8) | resultBytes[i]; } return result | (1ull << 63); } uint64_t generateMethodParamsId(uint64_t parentId, uint16_t methodOrdinal, bool isResults) { // Compute ID by hashing the concatenation of the parent ID, the method ordinal, and a // boolean indicating whether this is the params or the results, and then taking the first 8 // bytes. kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t) + 1]; for (uint i = 0; i < sizeof(uint64_t); i++) { bytes[i] = (parentId >> (i * 8)) & 0xff; } for (uint i = 0; i < sizeof(uint16_t); i++) { bytes[sizeof(uint64_t) + i] = (methodOrdinal >> (i * 8)) & 0xff; } bytes[sizeof(bytes) - 1] = isResults; TypeIdGenerator generator; generator.update(bytes); kj::ArrayPtr resultBytes = generator.finish(); uint64_t result = 0; for (uint i = 0; i < sizeof(uint64_t); i++) { result = (result << 8) | resultBytes[i]; } return result | (1ull << 63); } // The remainder of this file was derived from code placed in the public domain. // The original code bore the following notice: /* * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. * MD5 Message-Digest Algorithm (RFC 1321). * * Homepage: * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 * * Author: * Alexander Peslyak, better known as Solar Designer * * This software was written by Alexander Peslyak in 2001. No copyright is * claimed, and the software is hereby placed in the public domain. * In case this attempt to disclaim copyright and place the software in the * public domain is deemed null and void, then the software is * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the * general public under the following terms: * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * There's ABSOLUTELY NO WARRANTY, express or implied. * * (This is a heavily cut-down "BSD license".) * * This differs from Colin Plumb's older public domain implementation in that * no exactly 32-bit integer data type is required (any 32-bit or wider * unsigned integer data type will do), there's no compile-time endianness * configuration, and the function prototypes match OpenSSL's. No code from * Colin Plumb's implementation has been reused; this comment merely compares * the properties of the two independent implementations. * * The primary goals of this implementation are portability and ease of use. * It is meant to be fast, but not as fast as possible. Some known * optimizations are not included to reduce source code size and avoid * compile-time configuration. */ /* * The basic MD5 functions. * * F and G are optimized compared to their RFC 1321 definitions for * architectures that lack an AND-NOT instruction, just like in Colin Plumb's * implementation. */ #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | ~(z))) /* * The MD5 transformation for all four rounds. */ #define STEP(f, a, b, c, d, x, t, s) \ (a) += f((b), (c), (d)) + (x) + (t); \ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ (a) += (b); /* * SET reads 4 input bytes in little-endian byte order and stores them * in a properly aligned word in host byte order. * * The check for little-endian architectures that tolerate unaligned * memory accesses is just an optimization. Nothing will break if it * doesn't work. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ (*(uint *)&ptr[(n) * 4]) #define GET(n) \ SET(n) #else #define SET(n) \ (ctx.block[(n)] = \ (uint)ptr[(n) * 4] | \ ((uint)ptr[(n) * 4 + 1] << 8) | \ ((uint)ptr[(n) * 4 + 2] << 16) | \ ((uint)ptr[(n) * 4 + 3] << 24)) #define GET(n) \ (ctx.block[(n)]) #endif /* * This processes one or more 64-byte data blocks, but does NOT update * the bit counters. There are no alignment requirements. */ const kj::byte* TypeIdGenerator::body(const kj::byte* ptr, size_t size) { uint a, b, c, d; uint saved_a, saved_b, saved_c, saved_d; a = ctx.a; b = ctx.b; c = ctx.c; d = ctx.d; do { saved_a = a; saved_b = b; saved_c = c; saved_d = d; /* Round 1 */ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) STEP(F, c, d, a, b, SET(2), 0x242070db, 17) STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) /* Round 2 */ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) STEP(G, d, a, b, c, GET(10), 0x02441453, 9) STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) /* Round 3 */ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) /* Round 4 */ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) a += saved_a; b += saved_b; c += saved_c; d += saved_d; ptr += 64; } while (size -= 64); ctx.a = a; ctx.b = b; ctx.c = c; ctx.d = d; return ptr; } TypeIdGenerator::TypeIdGenerator() { ctx.a = 0x67452301; ctx.b = 0xefcdab89; ctx.c = 0x98badcfe; ctx.d = 0x10325476; ctx.lo = 0; ctx.hi = 0; } void TypeIdGenerator::update(kj::ArrayPtr dataArray) { KJ_REQUIRE(!finished, "already called TypeIdGenerator::finish()"); const kj::byte* data = dataArray.begin(); unsigned long size = dataArray.size(); uint saved_lo; unsigned long used, free; saved_lo = ctx.lo; if ((ctx.lo = (saved_lo + size) & 0x1fffffff) < saved_lo) ctx.hi++; ctx.hi += size >> 29; used = saved_lo & 0x3f; if (used) { free = 64 - used; if (size < free) { memcpy(&ctx.buffer[used], data, size); return; } memcpy(&ctx.buffer[used], data, free); data = data + free; size -= free; body(ctx.buffer, 64); } if (size >= 64) { data = body(data, size & ~(unsigned long)0x3f); size &= 0x3f; } memcpy(ctx.buffer, data, size); } kj::ArrayPtr TypeIdGenerator::finish() { if (!finished) { unsigned long used, free; used = ctx.lo & 0x3f; ctx.buffer[used++] = 0x80; free = 64 - used; if (free < 8) { memset(&ctx.buffer[used], 0, free); body(ctx.buffer, 64); used = 0; free = 64; } memset(&ctx.buffer[used], 0, free - 8); ctx.lo <<= 3; ctx.buffer[56] = ctx.lo; ctx.buffer[57] = ctx.lo >> 8; ctx.buffer[58] = ctx.lo >> 16; ctx.buffer[59] = ctx.lo >> 24; ctx.buffer[60] = ctx.hi; ctx.buffer[61] = ctx.hi >> 8; ctx.buffer[62] = ctx.hi >> 16; ctx.buffer[63] = ctx.hi >> 24; body(ctx.buffer, 64); // Store final result into ctx.buffer. ctx.buffer[0] = ctx.a; ctx.buffer[1] = ctx.a >> 8; ctx.buffer[2] = ctx.a >> 16; ctx.buffer[3] = ctx.a >> 24; ctx.buffer[4] = ctx.b; ctx.buffer[5] = ctx.b >> 8; ctx.buffer[6] = ctx.b >> 16; ctx.buffer[7] = ctx.b >> 24; ctx.buffer[8] = ctx.c; ctx.buffer[9] = ctx.c >> 8; ctx.buffer[10] = ctx.c >> 16; ctx.buffer[11] = ctx.c >> 24; ctx.buffer[12] = ctx.d; ctx.buffer[13] = ctx.d >> 8; ctx.buffer[14] = ctx.d >> 16; ctx.buffer[15] = ctx.d >> 24; finished = true; } return kj::arrayPtr(ctx.buffer, 16); } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/evolution-test.c++0000644000175000017500000007455014712011043023743 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This is a fuzz test which randomly generates a schema for a struct one change at a time. // Each modification is known a priori to be compatible or incompatible. The type is compiled // before and after the change and both versions are loaded into a SchemaLoader with the // expectation that this will succeed if they are compatible and fail if they are not. If // the types are expected to be compatible, the test also constructs an instance of the old // type and reads it as the new type, and vice versa. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include "compiler.h" #include #include #include #include #include #include #include namespace capnp { namespace compiler { namespace { static const kj::StringPtr RFC3092[] = {"foo", "bar", "baz", "qux"}; template T& chooseFrom(T (&arr)[size]) { return arr[rand() % size]; } template auto chooseFrom(T arr) -> decltype(arr[0]) { return arr[rand() % arr.size()]; } static Declaration::Builder addNested(Declaration::Builder parent) { auto oldNestedOrphan = parent.disownNestedDecls(); auto oldNested = oldNestedOrphan.get(); auto newNested = parent.initNestedDecls(oldNested.size() + 1); uint index = rand() % (oldNested.size() + 1); for (uint i = 0; i < index; i++) { newNested.setWithCaveats(i, oldNested[i]); } for (uint i = index + 1; i < newNested.size(); i++) { newNested.setWithCaveats(i, oldNested[i - 1]); } return newNested[index]; } struct TypeOption { kj::StringPtr name; kj::ConstFunction makeValue; }; static const TypeOption TYPE_OPTIONS[] = { { "Int32", [](Expression::Builder builder) { builder.setPositiveInt(rand() % (1 << 24)); }}, { "Float64", [](Expression::Builder builder) { builder.setPositiveInt(rand()); }}, { "Int8", [](Expression::Builder builder) { builder.setPositiveInt(rand() % 128); }}, { "UInt16", [](Expression::Builder builder) { builder.setPositiveInt(rand() % (1 << 16)); }}, { "Bool", [](Expression::Builder builder) { builder.initRelativeName().setValue("true"); }}, { "Text", [](Expression::Builder builder) { builder.setString(chooseFrom(RFC3092)); }}, { "StructType", [](Expression::Builder builder) { auto assignment = builder.initTuple(1)[0]; assignment.initNamed().setValue("i"); assignment.initValue().setPositiveInt(rand() % (1 << 24)); }}, { "EnumType", [](Expression::Builder builder) { builder.initRelativeName().setValue(chooseFrom(RFC3092)); }}, }; void setDeclName(Expression::Builder decl, kj::StringPtr name) { decl.initRelativeName().setValue(name); } static kj::ConstFunction randomizeType(Expression::Builder type) { auto option = &chooseFrom(TYPE_OPTIONS); if (rand() % 4 == 0) { auto app = type.initApplication(); setDeclName(app.initFunction(), "List"); setDeclName(app.initParams(1)[0].initValue(), option->name); return [option](Expression::Builder builder) { for (auto element: builder.initList(rand() % 4 + 1)) { option->makeValue(element); } }; } else { setDeclName(type, option->name); return option->makeValue.reference(); } } enum ChangeKind { NO_CHANGE, COMPATIBLE, INCOMPATIBLE, SUBTLY_COMPATIBLE // The change is technically compatible on the wire, but SchemaLoader will complain. }; struct ChangeInfo { ChangeKind kind; kj::String description; ChangeInfo(): kind(NO_CHANGE) {} ChangeInfo(ChangeKind kind, kj::StringPtr description) : kind(kind), description(kj::str(description)) {} ChangeInfo(ChangeKind kind, kj::String&& description) : kind(kind), description(kj::mv(description)) {} }; extern kj::ArrayPtr> STRUCT_MODS; extern kj::ArrayPtr> FIELD_MODS; // ================================================================================ static ChangeInfo declChangeName(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { auto name = decl.getName(); if (name.getValue().size() == 0) { // Naming an unnamed union. name.setValue(kj::str("unUnnamed", nextOrdinal)); return { SUBTLY_COMPATIBLE, "Assign name to unnamed union." }; } else { name.setValue(kj::str(name.getValue(), "Xx")); return { COMPATIBLE, "Rename declaration." }; } } static ChangeInfo structAddField(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { auto fieldDecl = addNested(decl); uint ordinal = nextOrdinal++; fieldDecl.initName().setValue(kj::str("f", ordinal)); fieldDecl.getId().initOrdinal().setValue(ordinal); auto field = fieldDecl.initField(); auto makeValue = randomizeType(field.initType()); if (rand() % 4 == 0) { makeValue(field.getDefaultValue().initValue()); } else { field.getDefaultValue().setNone(); } return { COMPATIBLE, "Add field." }; } static ChangeInfo structModifyField(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { auto nested = decl.getNestedDecls(); if (nested.size() == 0) { return { NO_CHANGE, "Modify field, but there were none to modify." }; } auto field = chooseFrom(nested); bool hasUnion = false; if (decl.isUnion()) { hasUnion = true; } else { for (auto n: nested) { if (n.isUnion() && n.getName().getValue().size() == 0) { hasUnion = true; break; } } } if (field.isGroup() || field.isUnion()) { return chooseFrom(STRUCT_MODS)(field, nextOrdinal, hasUnion); } else { return chooseFrom(FIELD_MODS)(field, nextOrdinal, hasUnion); } } static ChangeInfo structGroupifyFields( Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { // Place a random subset of the fields into a group. if (decl.isUnion()) { return { NO_CHANGE, "Randomly make a group out of some fields, but I can't do this to a union." }; } kj::Vector> groupified; kj::Vector> notGroupified; auto orphanage = Orphanage::getForMessageContaining(decl); for (auto nested: decl.getNestedDecls()) { if (rand() % 2) { groupified.add(orphanage.newOrphanCopy(nested.asReader())); } else { notGroupified.add(orphanage.newOrphanCopy(nested.asReader())); } } if (groupified.size() == 0) { return { NO_CHANGE, "Randomly make a group out of some fields, but I ended up choosing none of them." }; } auto newNested = decl.initNestedDecls(notGroupified.size() + 1); uint index = rand() % (notGroupified.size() + 1); for (uint i = 0; i < index; i++) { newNested.adoptWithCaveats(i, kj::mv(notGroupified[i])); } for (uint i = index; i < notGroupified.size(); i++) { newNested.adoptWithCaveats(i + 1, kj::mv(notGroupified[i])); } auto newGroup = newNested[index]; auto groupNested = newGroup.initNestedDecls(groupified.size()); for (uint i = 0; i < groupified.size(); i++) { groupNested.adoptWithCaveats(i, kj::mv(groupified[i])); } newGroup.initName().setValue(kj::str("g", nextOrdinal, "x", groupNested[0].getName().getValue())); newGroup.getId().setUnspecified(); newGroup.setGroup(); return { SUBTLY_COMPATIBLE, "Randomly group some set of existing fields." }; } static ChangeInfo structPermuteFields( Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { if (decl.getNestedDecls().size() == 0) { return { NO_CHANGE, "Permute field code order, but there were none." }; } auto oldOrphan = decl.disownNestedDecls(); auto old = oldOrphan.get(); KJ_STACK_ARRAY(uint, mapping, old.size(), 16, 64); for (uint i = 0; i < mapping.size(); i++) { mapping[i] = i; } for (uint i = mapping.size() - 1; i > 0; i--) { uint j = rand() % i; uint temp = mapping[j]; mapping[j] = mapping[i]; mapping[i] = temp; } auto newNested = decl.initNestedDecls(old.size()); for (uint i = 0; i < old.size(); i++) { newNested.setWithCaveats(i, old[mapping[i]]); } return { COMPATIBLE, "Permute field code order." }; } kj::ConstFunction STRUCT_MODS_[] = { structAddField, structAddField, structAddField, structModifyField, structModifyField, structModifyField, structPermuteFields, declChangeName, structGroupifyFields // do more rarely because it creates slowness }; kj::ArrayPtr> STRUCT_MODS = STRUCT_MODS_; // ================================================================================ static ChangeInfo fieldUpgradeList(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { // Upgrades a non-struct list to a struct list. auto field = decl.getField(); if (field.getDefaultValue().isValue()) { return { NO_CHANGE, "Upgrade primitive list to struct list, but it had a default value." }; } auto type = field.getType(); if (!type.isApplication()) { return { NO_CHANGE, "Upgrade primitive list to struct list, but it wasn't a list." }; } auto typeParams = type.getApplication().getParams(); auto elementType = typeParams[0].getValue(); auto relativeName = elementType.getRelativeName(); auto nameText = relativeName.asReader().getValue(); if (nameText == "StructType" || nameText.endsWith("Struct")) { return { NO_CHANGE, "Upgrade primitive list to struct list, but it was already a struct list."}; } if (nameText == "Bool") { return { NO_CHANGE, "Upgrade primitive list to struct list, but bool lists can't be upgraded."}; } relativeName.setValue(kj::str(nameText, "Struct")); return { COMPATIBLE, "Upgrade primitive list to struct list" }; } static ChangeInfo fieldExpandGroup(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { Declaration::Builder newDecl = decl.initNestedDecls(1)[0]; newDecl.adoptName(decl.disownName()); newDecl.getId().adoptOrdinal(decl.getId().disownOrdinal()); auto field = decl.getField(); auto newField = newDecl.initField(); newField.adoptType(field.disownType()); if (field.getDefaultValue().isValue()) { newField.getDefaultValue().adoptValue(field.getDefaultValue().disownValue()); } else { newField.getDefaultValue().setNone(); } decl.initName().setValue(kj::str("g", newDecl.getName().getValue())); decl.getId().setUnspecified(); if (rand() % 2 == 0) { decl.setGroup(); } else { decl.setUnion(); if (!scopeHasUnion && rand() % 2 == 0) { // Make it an unnamed union. decl.getName().setValue(""); } structAddField(decl, nextOrdinal, scopeHasUnion); // union must have two members } return { COMPATIBLE, "Wrap a field in a singleton group." }; } static ChangeInfo fieldChangeType(Declaration::Builder decl, uint& nextOrdinal, bool scopeHasUnion) { auto field = decl.getField(); if (field.getDefaultValue().isNone()) { // Change the type. auto type = field.getType(); while (type.isApplication()) { // Either change the list parameter, or revert to a non-list. if (rand() % 2) { type = type.getApplication().getParams()[0].getValue(); } else { type.initRelativeName(); } } auto typeName = type.getRelativeName(); if (typeName.asReader().getValue().startsWith("Text")) { typeName.setValue("Int32"); } else { typeName.setValue("Text"); } return { INCOMPATIBLE, "Change the type of a field." }; } else { // Change the default value. auto dval = field.getDefaultValue().getValue(); switch (dval.which()) { case Expression::UNKNOWN: KJ_FAIL_ASSERT("unknown value expression?"); case Expression::POSITIVE_INT: dval.setPositiveInt(dval.getPositiveInt() ^ 1); break; case Expression::NEGATIVE_INT: dval.setNegativeInt(dval.getNegativeInt() ^ 1); break; case Expression::FLOAT: dval.setFloat(-dval.getFloat()); break; case Expression::RELATIVE_NAME: { auto name = dval.getRelativeName(); auto nameText = name.asReader().getValue(); if (nameText == "true") { name.setValue("false"); } else if (nameText == "false") { name.setValue("true"); } else if (nameText == "foo") { name.setValue("bar"); } else { name.setValue("foo"); } break; } case Expression::STRING: case Expression::BINARY: case Expression::LIST: case Expression::TUPLE: return { NO_CHANGE, "Change the default value of a field, but it's a pointer field." }; case Expression::ABSOLUTE_NAME: case Expression::IMPORT: case Expression::EMBED: case Expression::APPLICATION: case Expression::MEMBER: KJ_FAIL_ASSERT("Unexpected expression type."); } return { INCOMPATIBLE, "Change the default value of a pritimive field." }; } } kj::ConstFunction FIELD_MODS_[] = { fieldUpgradeList, fieldExpandGroup, fieldChangeType, declChangeName }; kj::ArrayPtr> FIELD_MODS = FIELD_MODS_; // ================================================================================ uint getOrdinal(StructSchema::Field field) { auto proto = field.getProto(); if (proto.getOrdinal().isExplicit()) { return proto.getOrdinal().getExplicit(); } KJ_ASSERT(proto.isGroup()); auto group = field.getType().asStruct(); return getOrdinal(group.getFields()[0]); } Orphan makeExampleStruct( Orphanage orphanage, StructSchema schema, uint sharedOrdinalCount); void checkExampleStruct(DynamicStruct::Reader reader, uint sharedOrdinalCount); Orphan makeExampleValue( Orphanage orphanage, uint ordinal, Type type, uint sharedOrdinalCount) { switch (type.which()) { case schema::Type::INT32: return ordinal * 47327; case schema::Type::FLOAT64: return ordinal * 313.25; case schema::Type::INT8: return int(ordinal % 256) - 128; case schema::Type::UINT16: return ordinal * 13; case schema::Type::BOOL: return ordinal % 2 == 0; case schema::Type::TEXT: return orphanage.newOrphanCopy(Text::Reader(kj::str(ordinal))); case schema::Type::STRUCT: { auto structType = type.asStruct(); auto result = orphanage.newOrphan(structType); auto builder = result.get(); KJ_IF_MAYBE(fieldI, structType.findFieldByName("i")) { // Type is "StructType" builder.set(*fieldI, ordinal); } else { // Type is "Int32Struct" or the like. auto field = structType.getFieldByName("f0"); builder.adopt(field, makeExampleValue( orphanage, ordinal, field.getType(), sharedOrdinalCount)); } return kj::mv(result); } case schema::Type::ENUM: { auto enumerants = type.asEnum().getEnumerants(); return DynamicEnum(enumerants[ordinal %enumerants.size()]); } case schema::Type::LIST: { auto listType = type.asList(); auto elementType = listType.getElementType(); auto result = orphanage.newOrphan(listType, 1); result.get().adopt(0, makeExampleValue( orphanage, ordinal, elementType, sharedOrdinalCount)); return kj::mv(result); } default: KJ_FAIL_ASSERT("You added a new possible field type!"); } } void checkExampleValue(DynamicValue::Reader value, uint ordinal, schema::Type::Reader type, uint sharedOrdinalCount) { switch (type.which()) { case schema::Type::INT32: KJ_ASSERT(value.as() == ordinal * 47327); break; case schema::Type::FLOAT64: KJ_ASSERT(value.as() == ordinal * 313.25); break; case schema::Type::INT8: KJ_ASSERT(value.as() == int(ordinal % 256) - 128); break; case schema::Type::UINT16: KJ_ASSERT(value.as() == ordinal * 13); break; case schema::Type::BOOL: KJ_ASSERT(value.as() == (ordinal % 2 == 0)); break; case schema::Type::TEXT: KJ_ASSERT(value.as() == kj::str(ordinal)); break; case schema::Type::STRUCT: { auto structValue = value.as(); auto structType = structValue.getSchema(); KJ_IF_MAYBE(fieldI, structType.findFieldByName("i")) { // Type is "StructType" KJ_ASSERT(structValue.get(*fieldI).as() == ordinal); } else { // Type is "Int32Struct" or the like. auto field = structType.getFieldByName("f0"); checkExampleValue(structValue.get(field), ordinal, field.getProto().getSlot().getType(), sharedOrdinalCount); } break; } case schema::Type::ENUM: { auto enumerant = KJ_ASSERT_NONNULL(value.as().getEnumerant()); KJ_ASSERT(enumerant.getIndex() == ordinal % enumerant.getContainingEnum().getEnumerants().size()); break; } case schema::Type::LIST: checkExampleValue(value.as()[0], ordinal, type.getList().getElementType(), sharedOrdinalCount); break; default: KJ_FAIL_ASSERT("You added a new possible field type!"); } } void setExampleField(DynamicStruct::Builder builder, StructSchema::Field field, uint sharedOrdinalCount) { auto fieldProto = field.getProto(); switch (fieldProto.which()) { case schema::Field::SLOT: builder.adopt(field, makeExampleValue( Orphanage::getForMessageContaining(builder), getOrdinal(field), field.getType(), sharedOrdinalCount)); break; case schema::Field::GROUP: builder.adopt(field, makeExampleStruct( Orphanage::getForMessageContaining(builder), field.getType().asStruct(), sharedOrdinalCount)); break; } } void checkExampleField(DynamicStruct::Reader reader, StructSchema::Field field, uint sharedOrdinalCount) { auto fieldProto = field.getProto(); switch (fieldProto.which()) { case schema::Field::SLOT: { uint ordinal = getOrdinal(field); if (ordinal < sharedOrdinalCount) { checkExampleValue(reader.get(field), ordinal, fieldProto.getSlot().getType(), sharedOrdinalCount); } break; } case schema::Field::GROUP: checkExampleStruct(reader.get(field).as(), sharedOrdinalCount); break; } } Orphan makeExampleStruct( Orphanage orphanage, StructSchema schema, uint sharedOrdinalCount) { // Initialize all fields of the struct via reflection, such that they can be verified using // a different version of the struct. sharedOrdinalCount is the number of ordinals shared by // the two versions. This is used mainly to avoid setting union members that the other version // doesn't have. Orphan result = orphanage.newOrphan(schema); auto builder = result.get(); for (auto field: schema.getNonUnionFields()) { setExampleField(builder, field, sharedOrdinalCount); } auto unionFields = schema.getUnionFields(); // Pretend the union doesn't have any fields that aren't in the shared ordinal range. uint range = unionFields.size(); while (range > 0 && getOrdinal(unionFields[range - 1]) >= sharedOrdinalCount) { --range; } if (range > 0) { auto field = unionFields[getOrdinal(unionFields[0]) % range]; setExampleField(builder, field, sharedOrdinalCount); } return kj::mv(result); } void checkExampleStruct(DynamicStruct::Reader reader, uint sharedOrdinalCount) { auto schema = reader.getSchema(); for (auto field: schema.getNonUnionFields()) { checkExampleField(reader, field, sharedOrdinalCount); } auto unionFields = schema.getUnionFields(); // Pretend the union doesn't have any fields that aren't in the shared ordinal range. uint range = unionFields.size(); while (range > 0 && getOrdinal(unionFields[range - 1]) >= sharedOrdinalCount) { --range; } if (range > 0) { auto field = unionFields[getOrdinal(unionFields[0]) % range]; checkExampleField(reader, field, sharedOrdinalCount); } } // ================================================================================ class ModuleImpl final: public Module { public: explicit ModuleImpl(ParsedFile::Reader content): content(content) {} kj::StringPtr getSourceName() override { return "evolving-schema.capnp"; } Orphan loadContent(Orphanage orphanage) override { return orphanage.newOrphanCopy(content); } kj::Maybe importRelative(kj::StringPtr importPath) override { return nullptr; } kj::Maybe> embedRelative(kj::StringPtr embedPath) override { return nullptr; } void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { KJ_FAIL_ASSERT("Unexpected parse error.", startByte, endByte, message); } bool hadErrors() override { return false; } private: ParsedFile::Reader content; }; static void loadStructAndGroups(const SchemaLoader& src, SchemaLoader& dst, uint64_t id) { auto proto = src.get(id).getProto(); dst.load(proto); for (auto field: proto.getStruct().getFields()) { if (field.isGroup()) { loadStructAndGroups(src, dst, field.getGroup().getTypeId()); } } } static kj::Maybe loadFile( ParsedFile::Reader file, SchemaLoader& loader, bool allNodes, kj::Maybe>& messageBuilder, uint sharedOrdinalCount) { Compiler compiler; ModuleImpl module(file); KJ_ASSERT(compiler.add(module).getId() == 0x8123456789abcdefllu); if (allNodes) { // Eagerly compile and load the whole thing. compiler.eagerlyCompile(0x8123456789abcdefllu, Compiler::ALL_RELATED_NODES); KJ_IF_MAYBE(m, messageBuilder) { // Build an example struct using the compiled schema. m->get()->adoptRoot(makeExampleStruct( m->get()->getOrphanage(), compiler.getLoader().get(0x823456789abcdef1llu).asStruct(), sharedOrdinalCount)); } for (auto schema: compiler.getLoader().getAllLoaded()) { loader.load(schema.getProto()); } return nullptr; } else { // Compile the file root so that the children are findable, then load the specific child // we want. compiler.eagerlyCompile(0x8123456789abcdefllu, Compiler::NODE); KJ_IF_MAYBE(m, messageBuilder) { // Check that the example struct matches the compiled schema. auto root = m->get()->getRoot( compiler.getLoader().get(0x823456789abcdef1llu).asStruct()).asReader(); KJ_CONTEXT(root); checkExampleStruct(root, sharedOrdinalCount); } return kj::runCatchingExceptions([&]() { loadStructAndGroups(compiler.getLoader(), loader, 0x823456789abcdef1llu); }); } } bool checkChange(ParsedFile::Reader file1, ParsedFile::Reader file2, ChangeKind changeKind, uint sharedOrdinalCount) { // Try loading file1 followed by file2 into the same SchemaLoader, expecting it to behave // according to changeKind. Returns true if the files are both expected to be compatible and // actually are -- the main loop uses this to decide which version to keep kj::Maybe> exampleBuilder; if (changeKind != INCOMPATIBLE) { // For COMPATIBLE and SUBTLY_COMPATIBLE changes, build an example message with one schema // and check it with the other. exampleBuilder = kj::heap(); } SchemaLoader loader; loadFile(file1, loader, true, exampleBuilder, sharedOrdinalCount); auto exception = loadFile(file2, loader, false, exampleBuilder, sharedOrdinalCount); if (changeKind == COMPATIBLE) { KJ_IF_MAYBE(e, exception) { kj::getExceptionCallback().onFatalException(kj::mv(*e)); return false; } else { return true; } } else if (changeKind == INCOMPATIBLE) { KJ_ASSERT(exception != nullptr, file1, file2); return false; } else { KJ_ASSERT(changeKind == SUBTLY_COMPATIBLE); // SchemaLoader is allowed to throw an exception in this case, but we ignore it. return true; } } void doTest() { auto builder = kj::heap(); { // Set up the basic file decl. auto parsedFile = builder->initRoot(); auto file = parsedFile.initRoot(); file.setFile(); file.initId().initUid().setValue(0x8123456789abcdefllu); auto decls = file.initNestedDecls(3 + kj::size(TYPE_OPTIONS)); { auto decl = decls[0]; decl.initName().setValue("EvolvingStruct"); decl.initId().initUid().setValue(0x823456789abcdef1llu); decl.setStruct(); } { auto decl = decls[1]; decl.initName().setValue("StructType"); decl.setStruct(); auto fieldDecl = decl.initNestedDecls(1)[0]; fieldDecl.initName().setValue("i"); fieldDecl.getId().initOrdinal().setValue(0); auto field = fieldDecl.initField(); setDeclName(field.initType(), "UInt32"); } { auto decl = decls[2]; decl.initName().setValue("EnumType"); decl.setEnum(); auto enumerants = decl.initNestedDecls(4); for (uint i = 0; i < kj::size(RFC3092); i++) { auto enumerantDecl = enumerants[i]; enumerantDecl.initName().setValue(RFC3092[i]); enumerantDecl.getId().initOrdinal().setValue(i); enumerantDecl.setEnumerant(); } } // For each of TYPE_OPTIONS, declare a struct type that contains that type as its @0 field. for (uint i = 0; i < kj::size(TYPE_OPTIONS); i++) { auto decl = decls[3 + i]; auto& option = TYPE_OPTIONS[i]; decl.initName().setValue(kj::str(option.name, "Struct")); decl.setStruct(); auto fieldDecl = decl.initNestedDecls(1)[0]; fieldDecl.initName().setValue("f0"); fieldDecl.getId().initOrdinal().setValue(0); auto field = fieldDecl.initField(); setDeclName(field.initType(), option.name); uint ordinal = 1; for (auto j: kj::range(0, rand() % 4)) { (void)j; structAddField(decl, ordinal, false); } } } uint nextOrdinal = 0; for (uint i = 0; i < 96; i++) { uint oldOrdinalCount = nextOrdinal; auto newBuilder = kj::heap(); newBuilder->setRoot(builder->getRoot().asReader()); auto parsedFile = newBuilder->getRoot(); Declaration::Builder decl = parsedFile.getRoot().getNestedDecls()[0]; // Apply a random modification. ChangeInfo changeInfo; while (changeInfo.kind == NO_CHANGE) { auto& mod = chooseFrom(STRUCT_MODS); changeInfo = mod(decl, nextOrdinal, false); } KJ_CONTEXT(changeInfo.description); if (checkChange(builder->getRoot(), parsedFile, changeInfo.kind, oldOrdinalCount) && checkChange(parsedFile, builder->getRoot(), changeInfo.kind, oldOrdinalCount)) { builder = kj::mv(newBuilder); } } } class EvolutionTestMain { public: explicit EvolutionTestMain(kj::ProcessContext& context) : context(context) {} kj::MainFunc getMain() { return kj::MainBuilder(context, "(unknown version)", "Integration test / fuzzer which randomly modifies schemas is backwards-compatible ways " "and verifies that they do actually remain compatible.") .addOptionWithArg({"seed"}, KJ_BIND_METHOD(*this, setSeed), "", "Set random number seed to . By default, time() is used.") .callAfterParsing(KJ_BIND_METHOD(*this, run)) .build(); } kj::MainBuilder::Validity setSeed(kj::StringPtr value) { char* end; seed = strtol(value.cStr(), &end, 0); if (value.size() == 0 || *end != '\0') { return "not an integer"; } else { return true; } } kj::MainBuilder::Validity run() { // https://github.com/capnproto/capnproto/issues/344 describes an obscure bug in the layout // algorithm, the fix for which breaks backwards-compatibility for any schema triggering the // bug. In order to avoid silently breaking protocols, we are temporarily throwing an exception // in cases where this bug would have occurred, so that people can decide what to do. // However, the evolution test can occasionally trigger the bug (depending on the random path // it takes). Rather than try to avoid it, we disable the exception-throwing, because the bug // is actually fixed, and the exception is only there to raise awareness of the compatibility // concerns. // // On Linux, seed 1467142714 (for example) will trigger the exception (without this env var). #if defined(__MINGW32__) || defined(_MSC_VER) putenv("CAPNP_IGNORE_ISSUE_344=1"); #else setenv("CAPNP_IGNORE_ISSUE_344", "1", true); #endif srand(seed); { kj::String text = kj::str( "Randomly testing backwards-compatibility scenarios with seed: ", seed, "\n"); kj::FdOutputStream(STDOUT_FILENO).write(text.begin(), text.size()); } KJ_CONTEXT(seed, "PLEASE REPORT THIS FAILURE AND INCLUDE THE SEED"); doTest(); return true; } private: kj::ProcessContext& context; uint seed = time(nullptr); }; } // namespace } // namespace compiler } // namespace capnp KJ_MAIN(capnp::compiler::EvolutionTestMain); capnproto-c++-1.1.0/src/capnp/compiler/error-reporter.h0000644000175000017500000001033214731420004023600 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include #include #include CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { struct Resolution { uint32_t startByte; uint32_t endByte; struct Type { uint64_t typeId; }; struct Member { uint64_t parentTypeId; uint16_t ordinal; }; kj::OneOf target; }; class ErrorReporter { // Callback for reporting errors within a particular file. public: virtual void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) = 0; // Report an error at the given location in the input text. `startByte` and `endByte` indicate // the span of text that is erroneous. They may be equal, in which case the parser was only // able to identify where the error begins, not where it ends. template inline void addErrorOn(T&& decl, kj::StringPtr message) { // Works for any `T` that defines `getStartByte()` and `getEndByte()` methods, which many // of the Cap'n Proto types defined in `grammar.capnp` do. addError(decl.getStartByte(), decl.getEndByte(), message); } virtual bool hadErrors() = 0; // Return true if any errors have been reported, globally. The main use case for this callback // is to inhibit the reporting of errors which may have been caused by previous errors, or to // allow the compiler to bail out entirely if it gets confused and thinks this could be because // of previous errors. virtual void reportResolution(Resolution resolution) {}; // Report that an identifier parsed from the input resolved to a particular declaration. This may // be useful, for example, to implement a jump-to-definition in a code editor. // // This is not an error, but is reported through ErrorReporter because ErrorReporter tends to be // passed to all the right places to collect this information. }; class GlobalErrorReporter { // Callback for reporting errors in any file. public: struct SourcePos { uint byte; uint line; uint column; }; virtual void addError(const kj::ReadableDirectory& directory, kj::PathPtr path, SourcePos start, SourcePos end, kj::StringPtr message) = 0; // Report an error at the given location in the given file. virtual bool hadErrors() = 0; // Return true if any errors have been reported, globally. The main use case for this callback // is to inhibit the reporting of errors which may have been caused by previous errors, or to // allow the compiler to bail out entirely if it gets confused and thinks this could be because // of previous errors. }; class LineBreakTable { public: LineBreakTable(kj::ArrayPtr content); GlobalErrorReporter::SourcePos toSourcePos(uint32_t byteOffset) const; private: kj::Vector lineBreaks; // Byte offsets of the first byte in each source line. The first element is always zero. // Initialized the first time the module is loaded. }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/compiler.h0000644000175000017500000002745414731420004022436 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include "error-reporter.h" #include "generics.h" CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { class Module: public ErrorReporter { public: virtual kj::StringPtr getSourceName() = 0; // The name of the module file relative to the source tree. Used to decide where to output // generated code and to form the `displayName` in the schema. virtual Orphan loadContent(Orphanage orphanage) = 0; // Loads the module content, using the given orphanage to allocate objects if necessary. virtual kj::Maybe importRelative(kj::StringPtr importPath) = 0; // Find another module, relative to this one. Importing the same logical module twice should // produce the exact same object, comparable by identity. These objects are owned by some // outside pool that outlives the Compiler instance. virtual kj::Maybe> embedRelative(kj::StringPtr embedPath) = 0; // Read and return the content of a file specified using `embed`. virtual kj::ArrayPtr getResolutions() { return nullptr; } // Get the list of all resolutions reported using ErrorHandler::reportResolution(). }; class Compiler final: private SchemaLoader::LazyLoadCallback { // Cross-links separate modules (schema files) and translates them into schema nodes. // // This class is thread-safe, hence all its methods are const. class Node; public: enum AnnotationFlag { COMPILE_ANNOTATIONS, // Compile annotations normally. DROP_ANNOTATIONS // Do not compile any annotations, eagerly or lazily. All "annotations" fields in the schema // will be left empty. This is useful to avoid parsing imports that are used only for // annotations which you don't intend to use anyway. // // Unfortunately annotations cannot simply be compiled lazily because filling in the // "annotations" field at the usage site requires knowing the annotation's type, which requires // compiling the annotation, and the schema API has no particular way to detect when you // try to access the "annotations" field in order to lazily compile the annotations at that // point. }; explicit Compiler(AnnotationFlag annotationFlag = COMPILE_ANNOTATIONS); ~Compiler() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(Compiler); class CompiledType { // Represents a compiled type expression, from which you can traverse to nested types, apply // generics, etc. public: CompiledType clone(); // Make another CompiledType pointing to the same type. kj::Maybe getSchema(); // Evaluate to a type schema. Returns null if this "type" cannot actually be used as a field // type, e.g. because it's the pseudo-type representing a file's top-level scope. kj::Maybe getMember(kj::StringPtr name); // Look up a nested declaration. Returns null if there is no such member, or if the member is // not a type. kj::Maybe applyBrand(kj::Array arguments); // If this is a generic type, specializes apply a brand to it. Returns null if this is // not a generic type or too many arguments were specified. private: const Compiler& compiler; kj::ExternalMutexGuarded decl; CompiledType(const Compiler& compiler, kj::ExternalMutexGuarded decl) : compiler(compiler), decl(kj::mv(decl)) {} friend class Compiler; }; class ModuleScope { // Result of compiling a module. public: uint64_t getId() { return id; } CompiledType getRoot(); // Get a CompiledType representing the root, which can be used to programmatically look up // declarations. kj::Maybe evalType(Expression::Reader expression, ErrorReporter& errorReporter); // Evaluate some type expression within the scope of this module. // // Returns null if errors prevented evaluation; the errors will have been reported to // `errorReporter`. private: const Compiler& compiler; uint64_t id; Node& node; ModuleScope(const Compiler& compiler, uint64_t id, Node& node) : compiler(compiler), id(id), node(node) {} friend class Compiler; }; ModuleScope add(Module& module) const; // Add a module to the Compiler, returning a CompiledType representing the top-level scope of // the module. The module is parsed at the time `add()` is called, but not fully compiled -- // individual schema nodes are compiled lazily. If you want to force eager compilation, // see `eagerlyCompile()`, below. kj::Maybe lookup(uint64_t parent, kj::StringPtr childName) const; // Given the type ID of a schema node, find the ID of a node nested within it. Throws an // exception if the parent ID is not recognized; returns null if the parent has no child of the // given name. Neither the parent nor the child schema node is actually compiled. // // TODO(cleanup): This interface does not handle generics correctly. Use the // ModuleScope/CompiledType interface instead. kj::Maybe getSourceInfo(uint64_t id) const; // Get the SourceInfo for the given type ID, if available. Orphan> getFileImportTable(Module& module, Orphanage orphanage) const; // Build the import table for the CodeGeneratorRequest for the given module. Orphan> getAllSourceInfo(Orphanage orphanage) const; // Gets the SourceInfo structs for all nodes parsed by the compiler. enum Eagerness: uint32_t { // Flags specifying how eager to be about compilation. These are intended to be bitwise OR'd. // Used with the method `eagerlyCompile()`. // // Schema declarations can be compiled upfront, or they can be compiled lazily as they are // needed. Usually, the difference is not observable, but it is not a perfect abstraction. // The difference has the following effects: // * `getLoader().getAllLoaded()` only returns the schema nodes which have been compiled so // far. // * `getLoader().get()` (i.e. searching for a schema by ID) can only find schema nodes that // have either been compiled already, or which are referenced by schema nodes which have been // compiled already. This means that if the ID you pass in came from another schema node // compiled with the same compiler, there should be no observable difference, but if you // have an ID from elsewhere which you _a priori_ expect is defined in a particular schema // file, you will need to compile that file eagerly before you look up the node by ID. // * Errors are reported when they are encountered, so some errors will not be reported until // the node is actually compiled. // * If an imported file is not needed, it will never even be read from disk. // // The last point is the main reason why you might want to prefer lazy compilation: it allows // you to use a schema file with missing imports, so long as those missing imports are not // actually needed. // // For example, the flag combo: // EAGER_NODE | EAGER_CHILDREN | EAGER_DEPENDENCIES | EAGER_DEPENDENCY_PARENTS // will compile the entire given module, plus all direct dependencies of anything in that // module, plus all lexical ancestors of those dependencies. This is what the Cap'n Proto // compiler uses when building initial code generator requests. ALL_RELATED_NODES = ~0u, // Compile everything that is in any way related to the target node, including its entire // containing file and everything transitively imported by it. NODE = 1 << 0, // Eagerly compile the requested node, but not necessarily any of its parents, children, or // dependencies. PARENTS = 1 << 1, // Eagerly compile all lexical parents of the requested node. Only meaningful in conjunction // with NODE. CHILDREN = 1 << 2, // Eagerly compile all of the node's lexically nested nodes. Only meaningful in conjunction // with NODE. DEPENDENCIES = NODE << 15, // For all nodes compiled as a result of the above flags, also compile their direct // dependencies. E.g. if Foo is a struct which contains a field of type Bar, and Foo is // compiled, then also compile Bar. "Dependencies" are defined as field types, method // parameter and return types, and annotation types. Nested types and outer types are not // considered dependencies. DEPENDENCY_PARENTS = PARENTS * DEPENDENCIES, DEPENDENCY_CHILDREN = CHILDREN * DEPENDENCIES, DEPENDENCY_DEPENDENCIES = DEPENDENCIES * DEPENDENCIES, // Like PARENTS, CHILDREN, and DEPENDENCIES, but applies relative to dependency nodes rather // than the original requested node. Note that DEPENDENCY_DEPENDENCIES causes all transitive // dependencies of the requested node to be compiled. // // These flags are defined as multiples of the original flag and DEPENDENCIES so that we // can form the flags to use when traversing a dependency by shifting bits. }; void eagerlyCompile(uint64_t id, uint eagerness) const; // Force eager compilation of schema nodes related to the given ID. `eagerness` specifies which // related nodes should be compiled before returning. It is a bitwise OR of the possible values // of the `Eagerness` enum. // // If this returns and no errors have been reported, then it is guaranteed that the compiled // nodes can be found in the SchemaLoader returned by `getLoader()`. const SchemaLoader& getLoader() const { return loader; } SchemaLoader& getLoader() { return loader; } // Get a SchemaLoader backed by this compiler. Schema nodes will be lazily constructed as you // traverse them using this loader. void clearWorkspace() const; // The compiler builds a lot of temporary tables and data structures while it works. It's // useful to keep these around if more work is expected (especially if you are using lazy // compilation and plan to look up Schema nodes that haven't already been seen), but once // the SchemaLoader has everything you need, you can call clearWorkspace() to free up the // temporary space. Note that it's safe to call clearWorkspace() even if you do expect to // compile more nodes in the future; it may simply lead to redundant work if the discarded // structures are needed again. private: class Impl; kj::MutexGuarded> impl; SchemaLoader loader; class CompiledModule; class Alias; class ErrorIgnorer; void load(const SchemaLoader& loader, uint64_t id) const override; }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/module-loader.h0000644000175000017500000000447014712011043023344 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "compiler.h" #include "error-reporter.h" #include #include #include #include CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { class ModuleLoader { public: explicit ModuleLoader(GlobalErrorReporter& errorReporter); // Create a ModuleLoader that reports error messages to the given reporter. KJ_DISALLOW_COPY_AND_MOVE(ModuleLoader); ~ModuleLoader() noexcept(false); void addImportPath(const kj::ReadableDirectory& dir); // Add a directory to the list of paths that is searched for imports that start with a '/'. kj::Maybe loadModule(const kj::ReadableDirectory& dir, kj::PathPtr path); // Tries to load a module with the given path inside the given directory. Returns nullptr if the // file doesn't exist. void setFileIdsRequired(bool value); // Same as SchemaParser::setFileIdsRequired(). If set false, files will not be required to have // a top-level file ID; if missing a random one will be assigned. private: class Impl; kj::Own impl; class ModuleImpl; }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/compiler.c++0000644000175000017500000014744514712011043022560 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "compiler.h" #include "parser.h" // only for generateChildId() #include #include #include #include #include #include #include #include #include "node-translator.h" namespace capnp { namespace compiler { typedef std::unordered_map> SourceInfoMap; class Compiler::Alias { public: Alias(CompiledModule& module, Node& parent, const Expression::Reader& targetName) : module(module), parent(parent), targetName(targetName) {} kj::Maybe compile(); private: CompiledModule& module; Node& parent; Expression::Reader targetName; kj::Maybe target; Orphan brandOrphan; bool initialized = false; }; class Compiler::Node final: public Resolver { // Passes through four states: // - Stub: On initial construction, the Node is just a placeholder object. Its ID has been // determined, and it is placed in its parent's member table as well as the compiler's // nodes-by-ID table. // - Expanded: Nodes have been constructed for all of this Node's nested children. This happens // the first time a lookup is performed for one of those children. // - Bootstrap: A NodeTranslator has been built and advanced to the bootstrap phase. // - Finished: A final Schema object has been constructed. public: explicit Node(CompiledModule& module); // Create a root node representing the given file. May Node(Node& parent, const Declaration::Reader& declaration); // Create a child node. Node(kj::StringPtr name, Declaration::Which kind, List::Reader genericParams); // Create a dummy node representing a built-in declaration, like "Int32" or "true". uint64_t getId() { return id; } uint getParameterCount() { return genericParamCount; } Declaration::Which getKind() { return kind; } kj::Maybe getBootstrapSchema(); kj::Maybe getFinalSchema(); void loadFinalSchema(const SchemaLoader& loader); void traverse(uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo); // Get the final schema for this node, and also possibly traverse the node's children and // dependencies to ensure that they are loaded, depending on the mode. void addError(kj::StringPtr error); // Report an error on this Node. // implements Resolver --------------------------------------------- kj::Maybe resolve(kj::StringPtr name) override; kj::Maybe resolveMember(kj::StringPtr name) override; ResolvedDecl resolveBuiltin(Declaration::Which which) override; ResolvedDecl resolveId(uint64_t id) override; kj::Maybe getParent() override; ResolvedDecl getTopScope() override; kj::Maybe resolveBootstrapSchema( uint64_t id, schema::Brand::Reader brand) override; kj::Maybe resolveFinalSchema(uint64_t id) override; kj::Maybe resolveImport(kj::StringPtr name) override; kj::Maybe> readEmbed(kj::StringPtr name) override; kj::Maybe resolveBootstrapType(schema::Type::Reader type, Schema scope) override; private: CompiledModule* module; // null iff isBuiltin is true kj::Maybe parent; Declaration::Reader declaration; // AST of the declaration parsed from the schema file. May become invalid once the content // state has reached FINISHED. uint64_t id; // The ID of this node, either taken from the AST or computed based on the parent. Or, a dummy // value, if duplicates were detected. kj::StringPtr displayName; // Fully-qualified display name for this node. For files, this is just the file name, otherwise // it is "filename:Path.To.Decl". Declaration::Which kind; // Kind of node. uint genericParamCount; // Number of generic parameters. bool isBuiltin; // Whether this is a bulit-in declaration, like "Int32" or "true". uint32_t startByte; uint32_t endByte; // Start and end byte for reporting general errors. struct Content { inline Content(): state(STUB) {} enum State { STUB, EXPANDED, BOOTSTRAP, FINISHED }; State state; // Indicates which fields below are valid. inline bool stateHasReached(State minimumState) { return state >= minimumState; } inline void advanceState(State newState) { state = newState; } // EXPANDED ------------------------------------ typedef std::multimap> NestedNodesMap; NestedNodesMap nestedNodes; kj::Vector orderedNestedNodes; // multimap in case of duplicate member names -- we still want to compile them, even if it's an // error. typedef std::multimap> AliasMap; AliasMap aliases; // The "using" declarations. These are just links to nodes elsewhere. // BOOTSTRAP ----------------------------------- NodeTranslator* translator; // Node translator, allocated in the bootstrap arena. kj::Maybe bootstrapSchema; // The schema built in the bootstrap loader. Null if the bootstrap loader threw an exception. // FINISHED ------------------------------------ kj::Maybe finalSchema; // The completed schema, ready to load into the real schema loader. kj::Array auxSchemas; // Schemas for all auxiliary nodes built by the NodeTranslator. kj::Array sourceInfo; // All source info structs as built by the NodeTranslator. }; Content guardedContent; // Read using getContent() only! bool inGetContent = false; // True while getContent() is running; detects cycles. kj::Maybe loadedFinalSchema; // Copy of `finalSchema` as loaded into the final schema loader. This doesn't go away if the // workspace is destroyed. // --------------------------------------------- static uint64_t generateId(uint64_t parentId, kj::StringPtr declName, Declaration::Id::Reader declId); // Extract the ID from the declaration, or if it has none, generate one based on the name and // parent ID. static kj::StringPtr joinDisplayName(kj::Arena& arena, Node& parent, kj::StringPtr declName); // Join the parent's display name with the child's unqualified name to construct the child's // display name. kj::Maybe getContent(Content::State minimumState); // Advances the content to at least the given state and returns it. Returns null if getContent() // is being called recursively and the given state has not yet been reached, as this indicates // that the declaration recursively depends on itself. void traverseNodeDependencies(const schema::Node::Reader& schemaNode, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo); void traverseType(const schema::Type::Reader& type, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo); void traverseBrand(const schema::Brand::Reader& brand, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo); void traverseAnnotations(const List::Reader& annotations, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo); void traverseDependency(uint64_t depId, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo, bool ignoreIfNotFound = false); // Helpers for traverse(). }; class Compiler::CompiledModule { public: CompiledModule(Compiler::Impl& compiler, Module& parserModule); Compiler::Impl& getCompiler() { return compiler; } ErrorReporter& getErrorReporter() { return parserModule; } ParsedFile::Reader getParsedFile() { return content.getReader(); } Node& getRootNode() { return rootNode; } kj::StringPtr getSourceName() { return parserModule.getSourceName(); } kj::Maybe importRelative(kj::StringPtr importPath); kj::Maybe> embedRelative(kj::StringPtr importPath); Orphan> getFileImportTable(Orphanage orphanage); private: Compiler::Impl& compiler; Module& parserModule; MallocMessageBuilder contentArena; Orphan content; Node rootNode; }; class Compiler::Impl: public SchemaLoader::LazyLoadCallback { public: explicit Impl(AnnotationFlag annotationFlag); virtual ~Impl() noexcept(false); uint64_t add(Module& module); kj::Maybe lookup(uint64_t parent, kj::StringPtr childName); kj::Maybe getSourceInfo(uint64_t id); Orphan> getFileImportTable(Module& module, Orphanage orphanage); Orphan> getAllSourceInfo(Orphanage orphanage); void eagerlyCompile(uint64_t id, uint eagerness, const SchemaLoader& loader); CompiledModule& addInternal(Module& parsedModule); struct Workspace { // Scratch space where stuff can be allocated while working. The Workspace is available // whenever nodes are actively being compiled, then is destroyed once control exits the // compiler. Note that since nodes are compiled lazily, a new Workspace may have to be // constructed in order to compile more nodes later. MallocMessageBuilder message; Orphanage orphanage; // Orphanage for allocating temporary Cap'n Proto objects. kj::Arena arena; // Arena for allocating temporary native objects. Note that objects in `arena` may contain // pointers into `message` that will be manipulated on destruction, so `arena` must be declared // after `message`. SchemaLoader bootstrapLoader; // Loader used to load bootstrap schemas. The bootstrap schema nodes are similar to the final // versions except that any value expressions which depend on knowledge of other types (e.g. // default values for struct fields) are left unevaluated (the values in the schema are empty). // These bootstrap schemas can then be plugged into the dynamic API and used to evaluate these // remaining values. inline explicit Workspace(const SchemaLoader::LazyLoadCallback& loaderCallback) : orphanage(message.getOrphanage()), bootstrapLoader(loaderCallback) {} }; kj::Arena& getNodeArena() { return nodeArena; } // Arena where nodes and other permanent objects should be allocated. Workspace& getWorkspace() { return workspace; } // Temporary workspace that can be used to construct bootstrap objects. inline bool shouldCompileAnnotations() { return annotationFlag == AnnotationFlag::COMPILE_ANNOTATIONS; } void clearWorkspace(); // Reset the temporary workspace. uint64_t addNode(uint64_t desiredId, Node& node); // Add the given node to the by-ID map under the given ID. If another node with the same ID // already exists, choose a new one arbitrarily and use that instead. Return the ID that was // finally used. kj::Maybe findNode(uint64_t id); kj::Maybe lookupBuiltin(kj::StringPtr name); Node& getBuiltin(Declaration::Which which); void load(const SchemaLoader& loader, uint64_t id) const override; // SchemaLoader callback for the bootstrap loader. void loadFinal(const SchemaLoader& loader, uint64_t id); // Called from the SchemaLoader callback for the final loader. private: AnnotationFlag annotationFlag; kj::Arena nodeArena; // Arena used to allocate nodes and other permanent objects. std::unordered_map> modules; // Map of parser modules to compiler modules. Workspace workspace; // The temporary workspace. This field must be declared after `modules` because objects // allocated in the workspace may hold references to the compiled modules in `modules`. std::unordered_map nodesById; // Map of nodes by ID. std::unordered_map sourceInfoById; // Map of SourceInfos by ID, including SourceInfos for groups and param sturcts (which are not // listed in nodesById). std::map> builtinDecls; std::map builtinDeclsByKind; // Map of built-in declarations, like "Int32" and "List", which make up the global scope. uint64_t nextBogusId = 1000; // Counter for assigning bogus IDs to nodes whose real ID is a duplicate. }; // ======================================================================================= kj::Maybe Compiler::Alias::compile() { if (!initialized) { initialized = true; auto& workspace = module.getCompiler().getWorkspace(); brandOrphan = workspace.orphanage.newOrphan(); // If the Workspace is destroyed, revert the alias to the uninitialized state, because the // orphan we created is no longer valid in this case. workspace.arena.copy(kj::defer([this]() { initialized = false; brandOrphan = Orphan(); })); target = NodeTranslator::compileDecl( parent.getId(), parent.getParameterCount(), parent, module.getErrorReporter(), targetName, brandOrphan.get()); } return target; } // ======================================================================================= Compiler::Node::Node(CompiledModule& module) : module(&module), parent(nullptr), declaration(module.getParsedFile().getRoot()), id(generateId(0, declaration.getName().getValue(), declaration.getId())), displayName(module.getSourceName()), kind(declaration.which()), genericParamCount(declaration.getParameters().size()), isBuiltin(false) { auto name = declaration.getName(); if (name.getValue().size() > 0) { startByte = name.getStartByte(); endByte = name.getEndByte(); } else { startByte = declaration.getStartByte(); endByte = declaration.getEndByte(); } id = module.getCompiler().addNode(id, *this); } Compiler::Node::Node(Node& parent, const Declaration::Reader& declaration) : module(parent.module), parent(parent), declaration(declaration), id(generateId(parent.id, declaration.getName().getValue(), declaration.getId())), displayName(joinDisplayName(parent.module->getCompiler().getNodeArena(), parent, declaration.getName().getValue())), kind(declaration.which()), genericParamCount(declaration.getParameters().size()), isBuiltin(false) { auto name = declaration.getName(); if (name.getValue().size() > 0) { startByte = name.getStartByte(); endByte = name.getEndByte(); } else { startByte = declaration.getStartByte(); endByte = declaration.getEndByte(); } id = module->getCompiler().addNode(id, *this); } Compiler::Node::Node(kj::StringPtr name, Declaration::Which kind, List::Reader genericParams) : module(nullptr), parent(nullptr), // It's helpful if these have unique IDs. Real type IDs can't be under 2^31 anyway. id(1000 + static_cast(kind)), displayName(name), kind(kind), genericParamCount(genericParams.size()), isBuiltin(true), startByte(0), endByte(0) {} uint64_t Compiler::Node::generateId(uint64_t parentId, kj::StringPtr declName, Declaration::Id::Reader declId) { if (declId.isUid()) { return declId.getUid().getValue(); } return generateChildId(parentId, declName); } kj::StringPtr Compiler::Node::joinDisplayName( kj::Arena& arena, Node& parent, kj::StringPtr declName) { kj::ArrayPtr result = arena.allocateArray( parent.displayName.size() + declName.size() + 2); size_t separatorPos = parent.displayName.size(); memcpy(result.begin(), parent.displayName.begin(), separatorPos); result[separatorPos] = parent.parent == nullptr ? ':' : '.'; memcpy(result.begin() + separatorPos + 1, declName.begin(), declName.size()); result[result.size() - 1] = '\0'; return kj::StringPtr(result.begin(), result.size() - 1); } kj::Maybe Compiler::Node::getContent(Content::State minimumState) { KJ_REQUIRE(!isBuiltin, "illegal method call for built-in declaration"); auto& content = guardedContent; if (content.stateHasReached(minimumState)) { return content; } if (inGetContent) { addError("Declaration recursively depends on itself."); return nullptr; } inGetContent = true; KJ_DEFER(inGetContent = false); switch (content.state) { case Content::STUB: { if (minimumState <= Content::STUB) break; // Expand the child nodes. auto& arena = module->getCompiler().getNodeArena(); for (auto nestedDecl: declaration.getNestedDecls()) { switch (nestedDecl.which()) { case Declaration::FILE: case Declaration::CONST: case Declaration::ANNOTATION: case Declaration::ENUM: case Declaration::STRUCT: case Declaration::INTERFACE: { kj::Own subNode = arena.allocateOwn(*this, nestedDecl); kj::StringPtr name = nestedDecl.getName().getValue(); content.orderedNestedNodes.add(subNode); content.nestedNodes.insert(std::make_pair(name, kj::mv(subNode))); break; } case Declaration::USING: { kj::Own alias = arena.allocateOwn( *module, *this, nestedDecl.getUsing().getTarget()); kj::StringPtr name = nestedDecl.getName().getValue(); content.aliases.insert(std::make_pair(name, kj::mv(alias))); break; } case Declaration::ENUMERANT: case Declaration::FIELD: case Declaration::UNION: case Declaration::GROUP: case Declaration::METHOD: case Declaration::NAKED_ID: case Declaration::NAKED_ANNOTATION: // Not a node. Skip. break; default: KJ_FAIL_ASSERT("unknown declaration type", nestedDecl); break; } } content.advanceState(Content::EXPANDED); } KJ_FALLTHROUGH; case Content::EXPANDED: { if (minimumState <= Content::EXPANDED) break; // Construct the NodeTranslator. auto& workspace = module->getCompiler().getWorkspace(); auto schemaNode = workspace.orphanage.newOrphan(); auto builder = schemaNode.get(); builder.setId(id); builder.setDisplayName(displayName); // TODO(cleanup): Would be better if we could remember the prefix length from before we // added this decl's name to the end. KJ_IF_MAYBE(lastDot, displayName.findLast('.')) { builder.setDisplayNamePrefixLength(*lastDot + 1); } KJ_IF_MAYBE(lastColon, displayName.findLast(':')) { if (*lastColon > builder.getDisplayNamePrefixLength()) { builder.setDisplayNamePrefixLength(*lastColon + 1); } } KJ_IF_MAYBE(p, parent) { builder.setScopeId(p->id); } auto nestedNodes = builder.initNestedNodes(content.orderedNestedNodes.size()); auto nestedIter = nestedNodes.begin(); for (auto node: content.orderedNestedNodes) { nestedIter->setName(node->declaration.getName().getValue()); nestedIter->setId(node->id); ++nestedIter; } content.translator = &workspace.arena.allocate( *this, module->getErrorReporter(), declaration, kj::mv(schemaNode), module->getCompiler().shouldCompileAnnotations()); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){ auto nodeSet = content.translator->getBootstrapNode(); for (auto& auxNode: nodeSet.auxNodes) { workspace.bootstrapLoader.loadOnce(auxNode); } content.bootstrapSchema = workspace.bootstrapLoader.loadOnce(nodeSet.node); })) { content.bootstrapSchema = nullptr; // Only bother to report validation failures if we think we haven't seen any errors. // Otherwise we assume that the errors caused the validation failure. if (!module->getErrorReporter().hadErrors()) { addError(kj::str("Internal compiler bug: Bootstrap schema failed validation:\n", *exception)); } } // If the Workspace is destroyed, revert the node to the EXPANDED state, because the // NodeTranslator is no longer valid in this case. workspace.arena.copy(kj::defer([&content]() { content.bootstrapSchema = nullptr; if (content.state > Content::EXPANDED) { content.state = Content::EXPANDED; } })); content.advanceState(Content::BOOTSTRAP); } KJ_FALLTHROUGH; case Content::BOOTSTRAP: { if (minimumState <= Content::BOOTSTRAP) break; // Create the final schema. NodeTranslator::NodeSet nodeSet; if (content.bootstrapSchema == nullptr) { // Must have failed in an earlier stage. KJ_ASSERT(module->getErrorReporter().hadErrors()); nodeSet = content.translator->getBootstrapNode(); } else { nodeSet = content.translator->finish( module->getCompiler().getWorkspace().bootstrapLoader.getUnbound(id)); } content.finalSchema = nodeSet.node; content.auxSchemas = kj::mv(nodeSet.auxNodes); content.sourceInfo = kj::mv(nodeSet.sourceInfo); content.advanceState(Content::FINISHED); } KJ_FALLTHROUGH; case Content::FINISHED: break; } return content; } kj::Maybe Compiler::Node::getBootstrapSchema() { KJ_IF_MAYBE(schema, loadedFinalSchema) { // We don't need to rebuild the bootstrap schema if we already have a final schema. return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*schema); } else KJ_IF_MAYBE(content, getContent(Content::BOOTSTRAP)) { if (content->state == Content::FINISHED && content->bootstrapSchema == nullptr) { // The bootstrap schema was discarded. Copy it from the final schema. // (We can't just return the final schema because using it could trigger schema loader // callbacks that would deadlock.) KJ_IF_MAYBE(finalSchema, content->finalSchema) { return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*finalSchema); } else { return nullptr; } } else { return content->bootstrapSchema; } } else { return nullptr; } } kj::Maybe Compiler::Node::getFinalSchema() { KJ_IF_MAYBE(schema, loadedFinalSchema) { return *schema; } else KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { return content->finalSchema; } else { return nullptr; } } void Compiler::Node::loadFinalSchema(const SchemaLoader& loader) { KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){ KJ_IF_MAYBE(finalSchema, content->finalSchema) { KJ_MAP(auxSchema, content->auxSchemas) { return loader.loadOnce(auxSchema); }; loadedFinalSchema = loader.loadOnce(*finalSchema).getProto(); } })) { // Schema validation threw an exception. // Don't try loading this again. content->finalSchema = nullptr; // Only bother to report validation failures if we think we haven't seen any errors. // Otherwise we assume that the errors caused the validation failure. if (!module->getErrorReporter().hadErrors()) { addError(kj::str("Internal compiler bug: Schema failed validation:\n", *exception)); } } } } void Compiler::Node::traverse(uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo) { uint& slot = seen[this]; if ((slot & eagerness) == eagerness) { // We've already covered this node. return; } slot |= eagerness; KJ_IF_MAYBE(content, getContent(Content::FINISHED)) { loadFinalSchema(finalLoader); KJ_IF_MAYBE(schema, getFinalSchema()) { if (eagerness / DEPENDENCIES != 0) { // For traversing dependencies, discard the bits lower than DEPENDENCIES and replace // them with the bits above DEPENDENCIES shifted over. uint newEagerness = (eagerness & ~(DEPENDENCIES - 1)) | (eagerness / DEPENDENCIES); traverseNodeDependencies(*schema, newEagerness, seen, finalLoader, sourceInfo); for (auto& aux: content->auxSchemas) { traverseNodeDependencies(aux, newEagerness, seen, finalLoader, sourceInfo); } } } sourceInfo.addAll(content->sourceInfo); } if (eagerness & PARENTS) { KJ_IF_MAYBE(p, parent) { p->traverse(eagerness, seen, finalLoader, sourceInfo); } } if (eagerness & CHILDREN) { KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) { for (auto& child: content->orderedNestedNodes) { child->traverse(eagerness, seen, finalLoader, sourceInfo); } // Also traverse `using` declarations. for (auto& child: content->aliases) { child.second->compile(); } } } } void Compiler::Node::traverseNodeDependencies( const schema::Node::Reader& schemaNode, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo) { switch (schemaNode.which()) { case schema::Node::STRUCT: for (auto field: schemaNode.getStruct().getFields()) { switch (field.which()) { case schema::Field::SLOT: traverseType(field.getSlot().getType(), eagerness, seen, finalLoader, sourceInfo); break; case schema::Field::GROUP: // Aux node will be scanned later. break; } traverseAnnotations(field.getAnnotations(), eagerness, seen, finalLoader, sourceInfo); } break; case schema::Node::ENUM: for (auto enumerant: schemaNode.getEnum().getEnumerants()) { traverseAnnotations(enumerant.getAnnotations(), eagerness, seen, finalLoader, sourceInfo); } break; case schema::Node::INTERFACE: { auto interface = schemaNode.getInterface(); for (auto superclass: interface.getSuperclasses()) { uint64_t superclassId = superclass.getId(); if (superclassId != 0) { // if zero, we reported an error earlier traverseDependency(superclassId, eagerness, seen, finalLoader, sourceInfo); } traverseBrand(superclass.getBrand(), eagerness, seen, finalLoader, sourceInfo); } for (auto method: interface.getMethods()) { traverseDependency( method.getParamStructType(), eagerness, seen, finalLoader, sourceInfo, true); traverseBrand(method.getParamBrand(), eagerness, seen, finalLoader, sourceInfo); traverseDependency( method.getResultStructType(), eagerness, seen, finalLoader, sourceInfo, true); traverseBrand(method.getResultBrand(), eagerness, seen, finalLoader, sourceInfo); traverseAnnotations(method.getAnnotations(), eagerness, seen, finalLoader, sourceInfo); } break; } case schema::Node::CONST: traverseType(schemaNode.getConst().getType(), eagerness, seen, finalLoader, sourceInfo); break; case schema::Node::ANNOTATION: traverseType(schemaNode.getAnnotation().getType(), eagerness, seen, finalLoader, sourceInfo); break; default: break; } traverseAnnotations(schemaNode.getAnnotations(), eagerness, seen, finalLoader, sourceInfo); } void Compiler::Node::traverseType(const schema::Type::Reader& type, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo) { uint64_t id = 0; schema::Brand::Reader brand; switch (type.which()) { case schema::Type::STRUCT: id = type.getStruct().getTypeId(); brand = type.getStruct().getBrand(); break; case schema::Type::ENUM: id = type.getEnum().getTypeId(); brand = type.getEnum().getBrand(); break; case schema::Type::INTERFACE: id = type.getInterface().getTypeId(); brand = type.getInterface().getBrand(); break; case schema::Type::LIST: traverseType(type.getList().getElementType(), eagerness, seen, finalLoader, sourceInfo); return; default: return; } traverseDependency(id, eagerness, seen, finalLoader, sourceInfo); traverseBrand(brand, eagerness, seen, finalLoader, sourceInfo); } void Compiler::Node::traverseBrand( const schema::Brand::Reader& brand, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo) { for (auto scope: brand.getScopes()) { switch (scope.which()) { case schema::Brand::Scope::BIND: for (auto binding: scope.getBind()) { switch (binding.which()) { case schema::Brand::Binding::UNBOUND: break; case schema::Brand::Binding::TYPE: traverseType(binding.getType(), eagerness, seen, finalLoader, sourceInfo); break; } } break; case schema::Brand::Scope::INHERIT: break; } } } void Compiler::Node::traverseDependency(uint64_t depId, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo, bool ignoreIfNotFound) { KJ_IF_MAYBE(node, module->getCompiler().findNode(depId)) { node->traverse(eagerness, seen, finalLoader, sourceInfo); } else if (!ignoreIfNotFound) { KJ_FAIL_ASSERT("Dependency ID not present in compiler?", depId); } } void Compiler::Node::traverseAnnotations(const List::Reader& annotations, uint eagerness, std::unordered_map& seen, const SchemaLoader& finalLoader, kj::Vector& sourceInfo) { for (auto annotation: annotations) { KJ_IF_MAYBE(node, module->getCompiler().findNode(annotation.getId())) { node->traverse(eagerness, seen, finalLoader, sourceInfo); } } } void Compiler::Node::addError(kj::StringPtr error) { module->getErrorReporter().addError(startByte, endByte, error); } kj::Maybe Compiler::Node::resolve(kj::StringPtr name) { // Check members. KJ_IF_MAYBE(member, resolveMember(name)) { return *member; } // Check parameters. // TODO(perf): Maintain a map? auto params = declaration.getParameters(); for (uint i: kj::indices(params)) { if (params[i].getName() == name) { ResolveResult result; result.init(ResolvedParameter {id, i}); return result; } } // Check parent scope. KJ_IF_MAYBE(p, parent) { return p->resolve(name); } else KJ_IF_MAYBE(b, module->getCompiler().lookupBuiltin(name)) { ResolveResult result; result.init(ResolvedDecl { b->id, b->genericParamCount, 0, b->kind, b, nullptr }); return result; } else { return nullptr; } } kj::Maybe Compiler::Node::resolveMember(kj::StringPtr name) { if (isBuiltin) return nullptr; KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) { { auto iter = content->nestedNodes.find(name); if (iter != content->nestedNodes.end()) { Node* node = iter->second; ResolveResult result; result.init(ResolvedDecl { node->id, node->genericParamCount, id, node->kind, node, nullptr }); return result; } } { auto iter = content->aliases.find(name); if (iter != content->aliases.end()) { return iter->second->compile(); } } } return nullptr; } Resolver::ResolvedDecl Compiler::Node::resolveBuiltin(Declaration::Which which) { auto& b = module->getCompiler().getBuiltin(which); return { b.id, b.genericParamCount, 0, b.kind, &b, nullptr }; } Resolver::ResolvedDecl Compiler::Node::resolveId(uint64_t id) { auto& n = KJ_ASSERT_NONNULL(module->getCompiler().findNode(id)); uint64_t parentId = n.parent.map([](Node& n) { return n.id; }).orDefault(0); return { n.id, n.genericParamCount, parentId, n.kind, &n, nullptr }; } kj::Maybe Compiler::Node::getParent() { return parent.map([](Node& parent) { uint64_t scopeId = parent.parent.map([](Node& gp) { return gp.id; }).orDefault(0); return ResolvedDecl { parent.id, parent.genericParamCount, scopeId, parent.kind, &parent, nullptr }; }); } Resolver::ResolvedDecl Compiler::Node::getTopScope() { Node& node = module->getRootNode(); return ResolvedDecl { node.id, 0, 0, node.kind, &node, nullptr }; } kj::Maybe Compiler::Node::resolveBootstrapSchema( uint64_t id, schema::Brand::Reader brand) { KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) { // Make sure the bootstrap schema is loaded into the SchemaLoader. if (node->getBootstrapSchema() == nullptr) { return nullptr; } // Now we actually invoke get() to evaluate the brand. return module->getCompiler().getWorkspace().bootstrapLoader.get(id, brand); } else { KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before."); } } kj::Maybe Compiler::Node::resolveFinalSchema(uint64_t id) { KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) { return node->getFinalSchema(); } else { KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before."); } } kj::Maybe Compiler::Node::resolveImport(kj::StringPtr name) { KJ_IF_MAYBE(m, module->importRelative(name)) { Node& root = m->getRootNode(); return ResolvedDecl { root.id, 0, 0, root.kind, &root, nullptr }; } else { return nullptr; } } kj::Maybe> Compiler::Node::readEmbed(kj::StringPtr name) { return module->embedRelative(name); } kj::Maybe Compiler::Node::resolveBootstrapType(schema::Type::Reader type, Schema scope) { // TODO(someday): Arguably should return null if the type or its dependencies are placeholders. kj::Maybe result; KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { result = module->getCompiler().getWorkspace().bootstrapLoader.getType(type, scope); })) { result = nullptr; if (!module->getErrorReporter().hadErrors()) { addError(kj::str("Internal compiler bug: Bootstrap schema failed to load:\n", *exception)); } } return result; } // ======================================================================================= Compiler::CompiledModule::CompiledModule(Compiler::Impl& compiler, Module& parserModule) : compiler(compiler), parserModule(parserModule), content(parserModule.loadContent(contentArena.getOrphanage())), rootNode(*this) {} kj::Maybe Compiler::CompiledModule::importRelative( kj::StringPtr importPath) { return parserModule.importRelative(importPath).map( [this](Module& module) -> Compiler::CompiledModule& { return compiler.addInternal(module); }); } kj::Maybe> Compiler::CompiledModule::embedRelative(kj::StringPtr embedPath) { return parserModule.embedRelative(embedPath); } static void findImports(Expression::Reader exp, std::set& output) { switch (exp.which()) { case Expression::UNKNOWN: case Expression::POSITIVE_INT: case Expression::NEGATIVE_INT: case Expression::FLOAT: case Expression::STRING: case Expression::BINARY: case Expression::RELATIVE_NAME: case Expression::ABSOLUTE_NAME: case Expression::EMBED: break; case Expression::IMPORT: output.insert(exp.getImport().getValue()); break; case Expression::LIST: for (auto element: exp.getList()) { findImports(element, output); } break; case Expression::TUPLE: for (auto element: exp.getTuple()) { findImports(element.getValue(), output); } break; case Expression::APPLICATION: { auto app = exp.getApplication(); findImports(app.getFunction(), output); for (auto param: app.getParams()) { findImports(param.getValue(), output); } break; } case Expression::MEMBER: { findImports(exp.getMember().getParent(), output); break; } } } static void findImports(Declaration::ParamList::Reader paramList, std::set& output) { switch (paramList.which()) { case Declaration::ParamList::NAMED_LIST: for (auto param: paramList.getNamedList()) { findImports(param.getType(), output); for (auto ann: param.getAnnotations()) { findImports(ann.getName(), output); } } break; case Declaration::ParamList::TYPE: findImports(paramList.getType(), output); break; case Declaration::ParamList::STREAM: output.insert("/capnp/stream.capnp"); break; } } static void findImports(Declaration::Reader decl, std::set& output) { switch (decl.which()) { case Declaration::USING: findImports(decl.getUsing().getTarget(), output); break; case Declaration::CONST: findImports(decl.getConst().getType(), output); break; case Declaration::FIELD: findImports(decl.getField().getType(), output); break; case Declaration::INTERFACE: for (auto superclass: decl.getInterface().getSuperclasses()) { findImports(superclass, output); } break; case Declaration::METHOD: { auto method = decl.getMethod(); findImports(method.getParams(), output); if (method.getResults().isExplicit()) { findImports(method.getResults().getExplicit(), output); } break; } default: break; } for (auto ann: decl.getAnnotations()) { findImports(ann.getName(), output); } for (auto nested: decl.getNestedDecls()) { findImports(nested, output); } } Orphan> Compiler::CompiledModule::getFileImportTable(Orphanage orphanage) { // Build a table of imports for CodeGeneratorRequest.RequestedFile.imports. Note that we only // care about type imports, not constant value imports, since constant values (including default // values) are already embedded in full in the schema. In other words, we only need the imports // that would need to be #included in the generated code. std::set importNames; findImports(content.getReader().getRoot(), importNames); auto result = orphanage.newOrphan>( importNames.size()); auto builder = result.get(); uint i = 0; for (auto name: importNames) { // We presumably ran this import before, so it shouldn't throw now. auto entry = builder[i++]; entry.setId(KJ_ASSERT_NONNULL(importRelative(name)).rootNode.getId()); entry.setName(name); } return result; } // ======================================================================================= Compiler::Impl::Impl(AnnotationFlag annotationFlag) : annotationFlag(annotationFlag), workspace(*this) { // Reflectively interpret the members of Declaration.body. Any member prefixed by "builtin" // defines a builtin declaration visible in the global scope. StructSchema declSchema = Schema::from(); for (auto field: declSchema.getFields()) { auto fieldProto = field.getProto(); if (fieldProto.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT) { auto name = fieldProto.getName(); if (name.startsWith("builtin")) { kj::StringPtr symbolName = name.slice(strlen("builtin")); List::Reader params; for (auto annotation: fieldProto.getAnnotations()) { if (annotation.getId() == 0x94099c3f9eb32d6bull) { params = annotation.getValue().getList().getAs>(); break; } } Declaration::Which which = static_cast(fieldProto.getDiscriminantValue()); kj::Own newNode = nodeArena.allocateOwn(symbolName, which, params); builtinDeclsByKind[which] = newNode; builtinDecls[symbolName] = kj::mv(newNode); } } } } Compiler::Impl::~Impl() noexcept(false) {} void Compiler::Impl::clearWorkspace() { // Make sure we reconstruct the workspace even if destroying it throws an exception. KJ_DEFER(kj::ctor(workspace, *this)); kj::dtor(workspace); } Compiler::CompiledModule& Compiler::Impl::addInternal(Module& parsedModule) { kj::Own& slot = modules[&parsedModule]; if (slot.get() == nullptr) { slot = kj::heap(*this, parsedModule); } return *slot; } uint64_t Compiler::Impl::addNode(uint64_t desiredId, Node& node) { for (;;) { auto insertResult = nodesById.insert(std::make_pair(desiredId, &node)); if (insertResult.second) { return desiredId; } // Only report an error if this ID is not bogus. Actual IDs specified in the original source // code are required to have the upper bit set. Anything else must have been manufactured // at some point to cover up an error. if (desiredId & (1ull << 63)) { node.addError(kj::str("Duplicate ID @0x", kj::hex(desiredId), ".")); insertResult.first->second->addError( kj::str("ID @0x", kj::hex(desiredId), " originally used here.")); } // Assign a new bogus ID. desiredId = nextBogusId++; } } kj::Maybe Compiler::Impl::findNode(uint64_t id) { auto iter = nodesById.find(id); if (iter == nodesById.end()) { return nullptr; } else { return *iter->second; } } kj::Maybe Compiler::Impl::lookupBuiltin(kj::StringPtr name) { auto iter = builtinDecls.find(name); if (iter == builtinDecls.end()) { return nullptr; } else { return *iter->second; } } Compiler::Node& Compiler::Impl::getBuiltin(Declaration::Which which) { auto iter = builtinDeclsByKind.find(which); KJ_REQUIRE(iter != builtinDeclsByKind.end(), "invalid builtin", (uint)which); return *iter->second; } kj::Maybe Compiler::Impl::lookup(uint64_t parent, kj::StringPtr childName) { // Looking up members does not use the workspace, so we don't need to lock it. KJ_IF_MAYBE(parentNode, findNode(parent)) { KJ_IF_MAYBE(child, parentNode->resolveMember(childName)) { if (child->is()) { return child->get().id; } else { // An alias. We don't support looking up aliases with this method. return nullptr; } } else { return nullptr; } } else { KJ_FAIL_REQUIRE("lookup()s parameter 'parent' must be a known ID.", parent); } } kj::Maybe Compiler::Impl::getSourceInfo(uint64_t id) { auto iter = sourceInfoById.find(id); if (iter == sourceInfoById.end()) { return nullptr; } else { return iter->second; } } Orphan> Compiler::Impl::getFileImportTable(Module& module, Orphanage orphanage) { return addInternal(module).getFileImportTable(orphanage); } Orphan> Compiler::Impl::getAllSourceInfo(Orphanage orphanage) { auto result = orphanage.newOrphan>(sourceInfoById.size()); auto builder = result.get(); size_t i = 0; for (auto& entry: sourceInfoById) { builder.setWithCaveats(i++, entry.second); } return result; } void Compiler::Impl::eagerlyCompile(uint64_t id, uint eagerness, const SchemaLoader& finalLoader) { KJ_IF_MAYBE(node, findNode(id)) { std::unordered_map seen; kj::Vector sourceInfos; node->traverse(eagerness, seen, finalLoader, sourceInfos); // Copy the SourceInfo structures into permanent space so that they aren't invalidated when // clearWorkspace() is called. for (auto& sourceInfo: sourceInfos) { auto words = nodeArena.allocateArray(sourceInfo.totalSize().wordCount + 1); memset(words.begin(), 0, words.asBytes().size()); copyToUnchecked(sourceInfo, words); sourceInfoById.insert(std::make_pair(sourceInfo.getId(), readMessageUnchecked(words.begin()))); } } else { KJ_FAIL_REQUIRE("id did not come from this Compiler.", id); } } void Compiler::Impl::load(const SchemaLoader& loader, uint64_t id) const { // We know that this load() is only called from the bootstrap loader which is already protected // by our mutex, so we can drop thread-safety. auto& self = const_cast(*this); KJ_IF_MAYBE(node, self.findNode(id)) { node->getBootstrapSchema(); } } void Compiler::Impl::loadFinal(const SchemaLoader& loader, uint64_t id) { KJ_IF_MAYBE(node, findNode(id)) { node->loadFinalSchema(loader); } } // ======================================================================================= Compiler::Compiler(AnnotationFlag annotationFlag) : impl(kj::heap(annotationFlag)), loader(*this) {} Compiler::~Compiler() noexcept(false) {} Compiler::ModuleScope Compiler::add(Module& module) const { Node& root = impl.lockExclusive()->get()->addInternal(module).getRootNode(); return ModuleScope(*this, root.getId(), root); } kj::Maybe Compiler::lookup(uint64_t parent, kj::StringPtr childName) const { return impl.lockExclusive()->get()->lookup(parent, childName); } kj::Maybe Compiler::getSourceInfo(uint64_t id) const { return impl.lockExclusive()->get()->getSourceInfo(id); } Orphan> Compiler::getFileImportTable(Module& module, Orphanage orphanage) const { return impl.lockExclusive()->get()->getFileImportTable(module, orphanage); } Orphan> Compiler::getAllSourceInfo(Orphanage orphanage) const { return impl.lockExclusive()->get()->getAllSourceInfo(orphanage); } void Compiler::eagerlyCompile(uint64_t id, uint eagerness) const { impl.lockExclusive()->get()->eagerlyCompile(id, eagerness, loader); } void Compiler::clearWorkspace() const { impl.lockExclusive()->get()->clearWorkspace(); } void Compiler::load(const SchemaLoader& loader, uint64_t id) const { impl.lockExclusive()->get()->loadFinal(loader, id); } // ----------------------------------------------------------------------------- class Compiler::ErrorIgnorer: public ErrorReporter { public: void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override {} bool hadErrors() override { return false; } static ErrorIgnorer instance; }; Compiler::ErrorIgnorer Compiler::ErrorIgnorer::instance; kj::Maybe Compiler::CompiledType::getSchema() { capnp::word scratch[32]; memset(&scratch, 0, sizeof(scratch)); capnp::MallocMessageBuilder message(scratch); auto builder = message.getRoot(); { auto lock = compiler.impl.lockShared(); decl.get(lock).compileAsType(ErrorIgnorer::instance, builder); } // No need to pass `scope` as second parameter since CompiledType always represents a type // expression evaluated free-standing, not in any scope. return compiler.loader.getType(builder.asReader()); } Compiler::CompiledType Compiler::CompiledType::clone() { kj::ExternalMutexGuarded newDecl; { auto lock = compiler.impl.lockExclusive(); newDecl.set(lock, kj::cp(decl.get(lock))); } return CompiledType(compiler, kj::mv(newDecl)); } kj::Maybe Compiler::CompiledType::getMember(kj::StringPtr name) { kj::ExternalMutexGuarded newDecl; bool found = false; { auto lock = compiler.impl.lockShared(); KJ_IF_MAYBE(member, decl.get(lock).getMember(name, {})) { newDecl.set(lock, kj::mv(*member)); found = true; } } if (found) { return CompiledType(compiler, kj::mv(newDecl)); } else { return nullptr; } } kj::Maybe Compiler::CompiledType::applyBrand( kj::Array arguments) { kj::ExternalMutexGuarded newDecl; bool found = false; { auto lock = compiler.impl.lockShared(); auto args = KJ_MAP(arg, arguments) { return kj::mv(arg.decl.get(lock)); }; KJ_IF_MAYBE(member, decl.get(lock).applyParams(kj::mv(args), {})) { newDecl.set(lock, kj::mv(*member)); found = true; } } if (found) { return CompiledType(compiler, kj::mv(newDecl)); } else { return nullptr; } } Compiler::CompiledType Compiler::ModuleScope::getRoot() { kj::ExternalMutexGuarded newDecl; { auto lock = compiler.impl.lockExclusive(); auto brandScope = kj::refcounted(ErrorIgnorer::instance, node.getId(), 0, node); Resolver::ResolvedDecl decl { node.getId(), 0, 0, node.getKind(), &node, nullptr }; newDecl.set(lock, BrandedDecl(kj::mv(decl), kj::mv(brandScope), {})); } return CompiledType(compiler, kj::mv(newDecl)); } kj::Maybe Compiler::ModuleScope::evalType( Expression::Reader expression, ErrorReporter& errorReporter) { kj::ExternalMutexGuarded newDecl; bool found = false; { auto lock = compiler.impl.lockExclusive(); auto brandScope = kj::refcounted(errorReporter, node.getId(), 0, node); KJ_IF_MAYBE(result, brandScope->compileDeclExpression( expression, node, ImplicitParams::none())) { newDecl.set(lock, kj::mv(*result)); found = true; }; } if (found) { return CompiledType(compiler, kj::mv(newDecl)); } else { return nullptr; } } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/grammar.capnp.h0000644000175000017500000105504214731562162023361 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: grammar.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(e75816b56529d464); CAPNP_DECLARE_SCHEMA(991c7a3693d62cf2); CAPNP_DECLARE_SCHEMA(90f2a60678fd2367); CAPNP_DECLARE_SCHEMA(8e207d4dfe54d0de); CAPNP_DECLARE_SCHEMA(c90246b71adedbaa); CAPNP_DECLARE_SCHEMA(aee8397040b0df7a); CAPNP_DECLARE_SCHEMA(aa28e1400d793359); CAPNP_DECLARE_SCHEMA(96efe787c17e83bb); CAPNP_DECLARE_SCHEMA(d5e71144af1ce175); CAPNP_DECLARE_SCHEMA(d00489d473826290); CAPNP_DECLARE_SCHEMA(fb5aeed95cdf6af9); CAPNP_DECLARE_SCHEMA(94099c3f9eb32d6b); CAPNP_DECLARE_SCHEMA(b3f66e7a79d81bcd); CAPNP_DECLARE_SCHEMA(fffe08a9a697d2a5); CAPNP_DECLARE_SCHEMA(e5104515fd88ea47); CAPNP_DECLARE_SCHEMA(89f0c973c103ae96); CAPNP_DECLARE_SCHEMA(e93164a80bfe2ccf); CAPNP_DECLARE_SCHEMA(b348322a8dcf0d0c); CAPNP_DECLARE_SCHEMA(8f2622208fb358c8); CAPNP_DECLARE_SCHEMA(d0d1a21de617951f); CAPNP_DECLARE_SCHEMA(992a90eaf30235d3); CAPNP_DECLARE_SCHEMA(eb971847d617c0b9); CAPNP_DECLARE_SCHEMA(c6238c7d62d65173); CAPNP_DECLARE_SCHEMA(9cb9e86e3198037f); CAPNP_DECLARE_SCHEMA(84e4f3f5a807605c); } // namespace schemas } // namespace capnp namespace capnp { namespace compiler { struct LocatedText { LocatedText() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e75816b56529d464, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct LocatedInteger { LocatedInteger() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(991c7a3693d62cf2, 2, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct LocatedFloat { LocatedFloat() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(90f2a60678fd2367, 2, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Expression { Expression() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNKNOWN, POSITIVE_INT, NEGATIVE_INT, FLOAT, STRING, RELATIVE_NAME, LIST, TUPLE, BINARY, APPLICATION, MEMBER, ABSOLUTE_NAME, IMPORT, EMBED, }; struct Param; struct Application; struct Member; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(8e207d4dfe54d0de, 3, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Expression::Param { Param() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNNAMED, NAMED, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c90246b71adedbaa, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Expression::Application { Application() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(aee8397040b0df7a, 3, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Expression::Member { Member() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(aa28e1400d793359, 3, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration { Declaration() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { FILE, USING, CONST, ENUM, ENUMERANT, STRUCT, FIELD, UNION, GROUP, INTERFACE, METHOD, ANNOTATION, NAKED_ID, NAKED_ANNOTATION, BUILTIN_VOID, BUILTIN_BOOL, BUILTIN_INT8, BUILTIN_INT16, BUILTIN_INT32, BUILTIN_INT64, BUILTIN_U_INT8, BUILTIN_U_INT16, BUILTIN_U_INT32, BUILTIN_U_INT64, BUILTIN_FLOAT32, BUILTIN_FLOAT64, BUILTIN_TEXT, BUILTIN_DATA, BUILTIN_LIST, BUILTIN_OBJECT, BUILTIN_ANY_POINTER, BUILTIN_ANY_STRUCT, BUILTIN_ANY_LIST, BUILTIN_CAPABILITY, }; struct BrandParameter; struct AnnotationApplication; struct ParamList; struct Param; struct Id; struct Using; struct Const; struct Field; struct Interface; struct Method; struct Annotation; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(96efe787c17e83bb, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::BrandParameter { BrandParameter() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d5e71144af1ce175, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::AnnotationApplication { AnnotationApplication() = delete; class Reader; class Builder; class Pipeline; struct Value; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d00489d473826290, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::AnnotationApplication::Value { Value() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NONE, EXPRESSION, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(fb5aeed95cdf6af9, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::ParamList { ParamList() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NAMED_LIST, TYPE, STREAM, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b3f66e7a79d81bcd, 2, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Param { Param() = delete; class Reader; class Builder; class Pipeline; struct DefaultValue; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(fffe08a9a697d2a5, 2, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Param::DefaultValue { DefaultValue() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NONE, VALUE, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e5104515fd88ea47, 2, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Id { Id() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNSPECIFIED, UID, ORDINAL, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(89f0c973c103ae96, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Using { Using() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e93164a80bfe2ccf, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Const { Const() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b348322a8dcf0d0c, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Field { Field() = delete; class Reader; class Builder; class Pipeline; struct DefaultValue; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(8f2622208fb358c8, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Field::DefaultValue { DefaultValue() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NONE, VALUE, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d0d1a21de617951f, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Interface { Interface() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(992a90eaf30235d3, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Method { Method() = delete; class Reader; class Builder; class Pipeline; struct Results; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(eb971847d617c0b9, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Method::Results { Results() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NONE, EXPLICIT, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c6238c7d62d65173, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Declaration::Annotation { Annotation() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9cb9e86e3198037f, 2, 8) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct ParsedFile { ParsedFile() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(84e4f3f5a807605c, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class LocatedText::Reader { public: typedef LocatedText Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasValue() const; inline ::capnp::Text::Reader getValue() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class LocatedText::Builder { public: typedef LocatedText Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasValue(); inline ::capnp::Text::Builder getValue(); inline void setValue( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initValue(unsigned int size); inline void adoptValue(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownValue(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class LocatedText::Pipeline { public: typedef LocatedText Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class LocatedInteger::Reader { public: typedef LocatedInteger Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getValue() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class LocatedInteger::Builder { public: typedef LocatedInteger Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getValue(); inline void setValue( ::uint64_t value); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class LocatedInteger::Pipeline { public: typedef LocatedInteger Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class LocatedFloat::Reader { public: typedef LocatedFloat Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline double getValue() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class LocatedFloat::Builder { public: typedef LocatedFloat Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline double getValue(); inline void setValue(double value); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class LocatedFloat::Pipeline { public: typedef LocatedFloat Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Expression::Reader { public: typedef Expression Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnknown() const; inline ::capnp::Void getUnknown() const; inline bool isPositiveInt() const; inline ::uint64_t getPositiveInt() const; inline bool isNegativeInt() const; inline ::uint64_t getNegativeInt() const; inline bool isFloat() const; inline double getFloat() const; inline bool isString() const; inline bool hasString() const; inline ::capnp::Text::Reader getString() const; inline bool isRelativeName() const; inline bool hasRelativeName() const; inline ::capnp::compiler::LocatedText::Reader getRelativeName() const; inline bool isList() const; inline bool hasList() const; inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader getList() const; inline bool isTuple() const; inline bool hasTuple() const; inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader getTuple() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool isBinary() const; inline bool hasBinary() const; inline ::capnp::Data::Reader getBinary() const; inline bool isApplication() const; inline typename Application::Reader getApplication() const; inline bool isMember() const; inline typename Member::Reader getMember() const; inline bool isAbsoluteName() const; inline bool hasAbsoluteName() const; inline ::capnp::compiler::LocatedText::Reader getAbsoluteName() const; inline bool isImport() const; inline bool hasImport() const; inline ::capnp::compiler::LocatedText::Reader getImport() const; inline bool isEmbed() const; inline bool hasEmbed() const; inline ::capnp::compiler::LocatedText::Reader getEmbed() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Expression::Builder { public: typedef Expression Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnknown(); inline ::capnp::Void getUnknown(); inline void setUnknown( ::capnp::Void value = ::capnp::VOID); inline bool isPositiveInt(); inline ::uint64_t getPositiveInt(); inline void setPositiveInt( ::uint64_t value); inline bool isNegativeInt(); inline ::uint64_t getNegativeInt(); inline void setNegativeInt( ::uint64_t value); inline bool isFloat(); inline double getFloat(); inline void setFloat(double value); inline bool isString(); inline bool hasString(); inline ::capnp::Text::Builder getString(); inline void setString( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initString(unsigned int size); inline void adoptString(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownString(); inline bool isRelativeName(); inline bool hasRelativeName(); inline ::capnp::compiler::LocatedText::Builder getRelativeName(); inline void setRelativeName( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initRelativeName(); inline void adoptRelativeName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownRelativeName(); inline bool isList(); inline bool hasList(); inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder getList(); inline void setList( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder initList(unsigned int size); inline void adoptList(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> disownList(); inline bool isTuple(); inline bool hasTuple(); inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder getTuple(); inline void setTuple( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder initTuple(unsigned int size); inline void adoptTuple(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> disownTuple(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool isBinary(); inline bool hasBinary(); inline ::capnp::Data::Builder getBinary(); inline void setBinary( ::capnp::Data::Reader value); inline ::capnp::Data::Builder initBinary(unsigned int size); inline void adoptBinary(::capnp::Orphan< ::capnp::Data>&& value); inline ::capnp::Orphan< ::capnp::Data> disownBinary(); inline bool isApplication(); inline typename Application::Builder getApplication(); inline typename Application::Builder initApplication(); inline bool isMember(); inline typename Member::Builder getMember(); inline typename Member::Builder initMember(); inline bool isAbsoluteName(); inline bool hasAbsoluteName(); inline ::capnp::compiler::LocatedText::Builder getAbsoluteName(); inline void setAbsoluteName( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initAbsoluteName(); inline void adoptAbsoluteName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownAbsoluteName(); inline bool isImport(); inline bool hasImport(); inline ::capnp::compiler::LocatedText::Builder getImport(); inline void setImport( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initImport(); inline void adoptImport(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownImport(); inline bool isEmbed(); inline bool hasEmbed(); inline ::capnp::compiler::LocatedText::Builder getEmbed(); inline void setEmbed( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initEmbed(); inline void adoptEmbed(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownEmbed(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Expression::Pipeline { public: typedef Expression Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Expression::Param::Reader { public: typedef Param Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnnamed() const; inline ::capnp::Void getUnnamed() const; inline bool isNamed() const; inline bool hasNamed() const; inline ::capnp::compiler::LocatedText::Reader getNamed() const; inline bool hasValue() const; inline ::capnp::compiler::Expression::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Expression::Param::Builder { public: typedef Param Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnnamed(); inline ::capnp::Void getUnnamed(); inline void setUnnamed( ::capnp::Void value = ::capnp::VOID); inline bool isNamed(); inline bool hasNamed(); inline ::capnp::compiler::LocatedText::Builder getNamed(); inline void setNamed( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initNamed(); inline void adoptNamed(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownNamed(); inline bool hasValue(); inline ::capnp::compiler::Expression::Builder getValue(); inline void setValue( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Expression::Param::Pipeline { public: typedef Param Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Expression::Application::Reader { public: typedef Application Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasFunction() const; inline ::capnp::compiler::Expression::Reader getFunction() const; inline bool hasParams() const; inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader getParams() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Expression::Application::Builder { public: typedef Application Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasFunction(); inline ::capnp::compiler::Expression::Builder getFunction(); inline void setFunction( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initFunction(); inline void adoptFunction(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownFunction(); inline bool hasParams(); inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder getParams(); inline void setParams( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder initParams(unsigned int size); inline void adoptParams(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> disownParams(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Expression::Application::Pipeline { public: typedef Application Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getFunction(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Expression::Member::Reader { public: typedef Member Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasParent() const; inline ::capnp::compiler::Expression::Reader getParent() const; inline bool hasName() const; inline ::capnp::compiler::LocatedText::Reader getName() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Expression::Member::Builder { public: typedef Member Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasParent(); inline ::capnp::compiler::Expression::Builder getParent(); inline void setParent( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initParent(); inline void adoptParent(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownParent(); inline bool hasName(); inline ::capnp::compiler::LocatedText::Builder getName(); inline void setName( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initName(); inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Expression::Member::Pipeline { public: typedef Member Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getParent(); inline ::capnp::compiler::LocatedText::Pipeline getName(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Reader { public: typedef Declaration Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool hasName() const; inline ::capnp::compiler::LocatedText::Reader getName() const; inline typename Id::Reader getId() const; inline bool hasNestedDecls() const; inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader getNestedDecls() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool hasDocComment() const; inline ::capnp::Text::Reader getDocComment() const; inline bool isFile() const; inline ::capnp::Void getFile() const; inline bool isUsing() const; inline typename Using::Reader getUsing() const; inline bool isConst() const; inline typename Const::Reader getConst() const; inline bool isEnum() const; inline ::capnp::Void getEnum() const; inline bool isEnumerant() const; inline ::capnp::Void getEnumerant() const; inline bool isStruct() const; inline ::capnp::Void getStruct() const; inline bool isField() const; inline typename Field::Reader getField() const; inline bool isUnion() const; inline ::capnp::Void getUnion() const; inline bool isGroup() const; inline ::capnp::Void getGroup() const; inline bool isInterface() const; inline typename Interface::Reader getInterface() const; inline bool isMethod() const; inline typename Method::Reader getMethod() const; inline bool isAnnotation() const; inline typename Annotation::Reader getAnnotation() const; inline bool isNakedId() const; inline bool hasNakedId() const; inline ::capnp::compiler::LocatedInteger::Reader getNakedId() const; inline bool isNakedAnnotation() const; inline bool hasNakedAnnotation() const; inline ::capnp::compiler::Declaration::AnnotationApplication::Reader getNakedAnnotation() const; inline bool isBuiltinVoid() const; inline ::capnp::Void getBuiltinVoid() const; inline bool isBuiltinBool() const; inline ::capnp::Void getBuiltinBool() const; inline bool isBuiltinInt8() const; inline ::capnp::Void getBuiltinInt8() const; inline bool isBuiltinInt16() const; inline ::capnp::Void getBuiltinInt16() const; inline bool isBuiltinInt32() const; inline ::capnp::Void getBuiltinInt32() const; inline bool isBuiltinInt64() const; inline ::capnp::Void getBuiltinInt64() const; inline bool isBuiltinUInt8() const; inline ::capnp::Void getBuiltinUInt8() const; inline bool isBuiltinUInt16() const; inline ::capnp::Void getBuiltinUInt16() const; inline bool isBuiltinUInt32() const; inline ::capnp::Void getBuiltinUInt32() const; inline bool isBuiltinUInt64() const; inline ::capnp::Void getBuiltinUInt64() const; inline bool isBuiltinFloat32() const; inline ::capnp::Void getBuiltinFloat32() const; inline bool isBuiltinFloat64() const; inline ::capnp::Void getBuiltinFloat64() const; inline bool isBuiltinText() const; inline ::capnp::Void getBuiltinText() const; inline bool isBuiltinData() const; inline ::capnp::Void getBuiltinData() const; inline bool isBuiltinList() const; inline ::capnp::Void getBuiltinList() const; inline bool isBuiltinObject() const; inline ::capnp::Void getBuiltinObject() const; inline bool isBuiltinAnyPointer() const; inline ::capnp::Void getBuiltinAnyPointer() const; inline bool hasParameters() const; inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader getParameters() const; inline bool isBuiltinAnyStruct() const; inline ::capnp::Void getBuiltinAnyStruct() const; inline bool isBuiltinAnyList() const; inline ::capnp::Void getBuiltinAnyList() const; inline bool isBuiltinCapability() const; inline ::capnp::Void getBuiltinCapability() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Builder { public: typedef Declaration Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool hasName(); inline ::capnp::compiler::LocatedText::Builder getName(); inline void setName( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initName(); inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); inline typename Id::Builder getId(); inline typename Id::Builder initId(); inline bool hasNestedDecls(); inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder getNestedDecls(); inline void setNestedDecls( ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder initNestedDecls(unsigned int size); inline void adoptNestedDecls(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>> disownNestedDecls(); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> disownAnnotations(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool hasDocComment(); inline ::capnp::Text::Builder getDocComment(); inline void setDocComment( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initDocComment(unsigned int size); inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); inline bool isFile(); inline ::capnp::Void getFile(); inline void setFile( ::capnp::Void value = ::capnp::VOID); inline bool isUsing(); inline typename Using::Builder getUsing(); inline typename Using::Builder initUsing(); inline bool isConst(); inline typename Const::Builder getConst(); inline typename Const::Builder initConst(); inline bool isEnum(); inline ::capnp::Void getEnum(); inline void setEnum( ::capnp::Void value = ::capnp::VOID); inline bool isEnumerant(); inline ::capnp::Void getEnumerant(); inline void setEnumerant( ::capnp::Void value = ::capnp::VOID); inline bool isStruct(); inline ::capnp::Void getStruct(); inline void setStruct( ::capnp::Void value = ::capnp::VOID); inline bool isField(); inline typename Field::Builder getField(); inline typename Field::Builder initField(); inline bool isUnion(); inline ::capnp::Void getUnion(); inline void setUnion( ::capnp::Void value = ::capnp::VOID); inline bool isGroup(); inline ::capnp::Void getGroup(); inline void setGroup( ::capnp::Void value = ::capnp::VOID); inline bool isInterface(); inline typename Interface::Builder getInterface(); inline typename Interface::Builder initInterface(); inline bool isMethod(); inline typename Method::Builder getMethod(); inline typename Method::Builder initMethod(); inline bool isAnnotation(); inline typename Annotation::Builder getAnnotation(); inline typename Annotation::Builder initAnnotation(); inline bool isNakedId(); inline bool hasNakedId(); inline ::capnp::compiler::LocatedInteger::Builder getNakedId(); inline void setNakedId( ::capnp::compiler::LocatedInteger::Reader value); inline ::capnp::compiler::LocatedInteger::Builder initNakedId(); inline void adoptNakedId(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownNakedId(); inline bool isNakedAnnotation(); inline bool hasNakedAnnotation(); inline ::capnp::compiler::Declaration::AnnotationApplication::Builder getNakedAnnotation(); inline void setNakedAnnotation( ::capnp::compiler::Declaration::AnnotationApplication::Reader value); inline ::capnp::compiler::Declaration::AnnotationApplication::Builder initNakedAnnotation(); inline void adoptNakedAnnotation(::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication>&& value); inline ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication> disownNakedAnnotation(); inline bool isBuiltinVoid(); inline ::capnp::Void getBuiltinVoid(); inline void setBuiltinVoid( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinBool(); inline ::capnp::Void getBuiltinBool(); inline void setBuiltinBool( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinInt8(); inline ::capnp::Void getBuiltinInt8(); inline void setBuiltinInt8( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinInt16(); inline ::capnp::Void getBuiltinInt16(); inline void setBuiltinInt16( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinInt32(); inline ::capnp::Void getBuiltinInt32(); inline void setBuiltinInt32( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinInt64(); inline ::capnp::Void getBuiltinInt64(); inline void setBuiltinInt64( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinUInt8(); inline ::capnp::Void getBuiltinUInt8(); inline void setBuiltinUInt8( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinUInt16(); inline ::capnp::Void getBuiltinUInt16(); inline void setBuiltinUInt16( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinUInt32(); inline ::capnp::Void getBuiltinUInt32(); inline void setBuiltinUInt32( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinUInt64(); inline ::capnp::Void getBuiltinUInt64(); inline void setBuiltinUInt64( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinFloat32(); inline ::capnp::Void getBuiltinFloat32(); inline void setBuiltinFloat32( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinFloat64(); inline ::capnp::Void getBuiltinFloat64(); inline void setBuiltinFloat64( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinText(); inline ::capnp::Void getBuiltinText(); inline void setBuiltinText( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinData(); inline ::capnp::Void getBuiltinData(); inline void setBuiltinData( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinList(); inline ::capnp::Void getBuiltinList(); inline void setBuiltinList( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinObject(); inline ::capnp::Void getBuiltinObject(); inline void setBuiltinObject( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinAnyPointer(); inline ::capnp::Void getBuiltinAnyPointer(); inline void setBuiltinAnyPointer( ::capnp::Void value = ::capnp::VOID); inline bool hasParameters(); inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder getParameters(); inline void setParameters( ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder initParameters(unsigned int size); inline void adoptParameters(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>> disownParameters(); inline bool isBuiltinAnyStruct(); inline ::capnp::Void getBuiltinAnyStruct(); inline void setBuiltinAnyStruct( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinAnyList(); inline ::capnp::Void getBuiltinAnyList(); inline void setBuiltinAnyList( ::capnp::Void value = ::capnp::VOID); inline bool isBuiltinCapability(); inline ::capnp::Void getBuiltinCapability(); inline void setBuiltinCapability( ::capnp::Void value = ::capnp::VOID); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Pipeline { public: typedef Declaration Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::LocatedText::Pipeline getName(); inline typename Id::Pipeline getId(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::BrandParameter::Reader { public: typedef BrandParameter Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::BrandParameter::Builder { public: typedef BrandParameter Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::BrandParameter::Pipeline { public: typedef BrandParameter Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::AnnotationApplication::Reader { public: typedef AnnotationApplication Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::compiler::Expression::Reader getName() const; inline typename Value::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::AnnotationApplication::Builder { public: typedef AnnotationApplication Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::compiler::Expression::Builder getName(); inline void setName( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initName(); inline void adoptName(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownName(); inline typename Value::Builder getValue(); inline typename Value::Builder initValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::AnnotationApplication::Pipeline { public: typedef AnnotationApplication Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getName(); inline typename Value::Pipeline getValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::AnnotationApplication::Value::Reader { public: typedef Value Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNone() const; inline ::capnp::Void getNone() const; inline bool isExpression() const; inline bool hasExpression() const; inline ::capnp::compiler::Expression::Reader getExpression() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::AnnotationApplication::Value::Builder { public: typedef Value Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNone(); inline ::capnp::Void getNone(); inline void setNone( ::capnp::Void value = ::capnp::VOID); inline bool isExpression(); inline bool hasExpression(); inline ::capnp::compiler::Expression::Builder getExpression(); inline void setExpression( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initExpression(); inline void adoptExpression(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownExpression(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::AnnotationApplication::Value::Pipeline { public: typedef Value Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::ParamList::Reader { public: typedef ParamList Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNamedList() const; inline bool hasNamedList() const; inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader getNamedList() const; inline bool isType() const; inline bool hasType() const; inline ::capnp::compiler::Expression::Reader getType() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool isStream() const; inline ::capnp::Void getStream() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::ParamList::Builder { public: typedef ParamList Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNamedList(); inline bool hasNamedList(); inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder getNamedList(); inline void setNamedList( ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder initNamedList(unsigned int size); inline void adoptNamedList(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>> disownNamedList(); inline bool isType(); inline bool hasType(); inline ::capnp::compiler::Expression::Builder getType(); inline void setType( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool isStream(); inline ::capnp::Void getStream(); inline void setStream( ::capnp::Void value = ::capnp::VOID); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::ParamList::Pipeline { public: typedef ParamList Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Param::Reader { public: typedef Param Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::compiler::LocatedText::Reader getName() const; inline bool hasType() const; inline ::capnp::compiler::Expression::Reader getType() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; inline typename DefaultValue::Reader getDefaultValue() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Param::Builder { public: typedef Param Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::compiler::LocatedText::Builder getName(); inline void setName( ::capnp::compiler::LocatedText::Reader value); inline ::capnp::compiler::LocatedText::Builder initName(); inline void adoptName(::capnp::Orphan< ::capnp::compiler::LocatedText>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedText> disownName(); inline bool hasType(); inline ::capnp::compiler::Expression::Builder getType(); inline void setType( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> disownAnnotations(); inline typename DefaultValue::Builder getDefaultValue(); inline typename DefaultValue::Builder initDefaultValue(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Param::Pipeline { public: typedef Param Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::LocatedText::Pipeline getName(); inline ::capnp::compiler::Expression::Pipeline getType(); inline typename DefaultValue::Pipeline getDefaultValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Param::DefaultValue::Reader { public: typedef DefaultValue Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNone() const; inline ::capnp::Void getNone() const; inline bool isValue() const; inline bool hasValue() const; inline ::capnp::compiler::Expression::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Param::DefaultValue::Builder { public: typedef DefaultValue Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNone(); inline ::capnp::Void getNone(); inline void setNone( ::capnp::Void value = ::capnp::VOID); inline bool isValue(); inline bool hasValue(); inline ::capnp::compiler::Expression::Builder getValue(); inline void setValue( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Param::DefaultValue::Pipeline { public: typedef DefaultValue Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Id::Reader { public: typedef Id Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnspecified() const; inline ::capnp::Void getUnspecified() const; inline bool isUid() const; inline bool hasUid() const; inline ::capnp::compiler::LocatedInteger::Reader getUid() const; inline bool isOrdinal() const; inline bool hasOrdinal() const; inline ::capnp::compiler::LocatedInteger::Reader getOrdinal() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Id::Builder { public: typedef Id Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnspecified(); inline ::capnp::Void getUnspecified(); inline void setUnspecified( ::capnp::Void value = ::capnp::VOID); inline bool isUid(); inline bool hasUid(); inline ::capnp::compiler::LocatedInteger::Builder getUid(); inline void setUid( ::capnp::compiler::LocatedInteger::Reader value); inline ::capnp::compiler::LocatedInteger::Builder initUid(); inline void adoptUid(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownUid(); inline bool isOrdinal(); inline bool hasOrdinal(); inline ::capnp::compiler::LocatedInteger::Builder getOrdinal(); inline void setOrdinal( ::capnp::compiler::LocatedInteger::Reader value); inline ::capnp::compiler::LocatedInteger::Builder initOrdinal(); inline void adoptOrdinal(::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value); inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> disownOrdinal(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Id::Pipeline { public: typedef Id Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Using::Reader { public: typedef Using Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasTarget() const; inline ::capnp::compiler::Expression::Reader getTarget() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Using::Builder { public: typedef Using Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasTarget(); inline ::capnp::compiler::Expression::Builder getTarget(); inline void setTarget( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initTarget(); inline void adoptTarget(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownTarget(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Using::Pipeline { public: typedef Using Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getTarget(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Const::Reader { public: typedef Const Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasType() const; inline ::capnp::compiler::Expression::Reader getType() const; inline bool hasValue() const; inline ::capnp::compiler::Expression::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Const::Builder { public: typedef Const Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasType(); inline ::capnp::compiler::Expression::Builder getType(); inline void setType( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); inline bool hasValue(); inline ::capnp::compiler::Expression::Builder getValue(); inline void setValue( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Const::Pipeline { public: typedef Const Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getType(); inline ::capnp::compiler::Expression::Pipeline getValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Field::Reader { public: typedef Field Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasType() const; inline ::capnp::compiler::Expression::Reader getType() const; inline typename DefaultValue::Reader getDefaultValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Field::Builder { public: typedef Field Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasType(); inline ::capnp::compiler::Expression::Builder getType(); inline void setType( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); inline typename DefaultValue::Builder getDefaultValue(); inline typename DefaultValue::Builder initDefaultValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Field::Pipeline { public: typedef Field Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getType(); inline typename DefaultValue::Pipeline getDefaultValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Field::DefaultValue::Reader { public: typedef DefaultValue Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNone() const; inline ::capnp::Void getNone() const; inline bool isValue() const; inline bool hasValue() const; inline ::capnp::compiler::Expression::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Field::DefaultValue::Builder { public: typedef DefaultValue Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNone(); inline ::capnp::Void getNone(); inline void setNone( ::capnp::Void value = ::capnp::VOID); inline bool isValue(); inline bool hasValue(); inline ::capnp::compiler::Expression::Builder getValue(); inline void setValue( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Field::DefaultValue::Pipeline { public: typedef DefaultValue Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Interface::Reader { public: typedef Interface Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasSuperclasses() const; inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader getSuperclasses() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Interface::Builder { public: typedef Interface Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasSuperclasses(); inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder getSuperclasses(); inline void setSuperclasses( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder initSuperclasses(unsigned int size); inline void adoptSuperclasses(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> disownSuperclasses(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Interface::Pipeline { public: typedef Interface Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Method::Reader { public: typedef Method Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasParams() const; inline ::capnp::compiler::Declaration::ParamList::Reader getParams() const; inline typename Results::Reader getResults() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Method::Builder { public: typedef Method Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasParams(); inline ::capnp::compiler::Declaration::ParamList::Builder getParams(); inline void setParams( ::capnp::compiler::Declaration::ParamList::Reader value); inline ::capnp::compiler::Declaration::ParamList::Builder initParams(); inline void adoptParams(::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value); inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> disownParams(); inline typename Results::Builder getResults(); inline typename Results::Builder initResults(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Method::Pipeline { public: typedef Method Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Declaration::ParamList::Pipeline getParams(); inline typename Results::Pipeline getResults(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Method::Results::Reader { public: typedef Results Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNone() const; inline ::capnp::Void getNone() const; inline bool isExplicit() const; inline bool hasExplicit() const; inline ::capnp::compiler::Declaration::ParamList::Reader getExplicit() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Method::Results::Builder { public: typedef Results Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNone(); inline ::capnp::Void getNone(); inline void setNone( ::capnp::Void value = ::capnp::VOID); inline bool isExplicit(); inline bool hasExplicit(); inline ::capnp::compiler::Declaration::ParamList::Builder getExplicit(); inline void setExplicit( ::capnp::compiler::Declaration::ParamList::Reader value); inline ::capnp::compiler::Declaration::ParamList::Builder initExplicit(); inline void adoptExplicit(::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value); inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> disownExplicit(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Method::Results::Pipeline { public: typedef Results Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Declaration::Annotation::Reader { public: typedef Annotation Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasType() const; inline ::capnp::compiler::Expression::Reader getType() const; inline bool getTargetsFile() const; inline bool getTargetsConst() const; inline bool getTargetsEnum() const; inline bool getTargetsEnumerant() const; inline bool getTargetsStruct() const; inline bool getTargetsField() const; inline bool getTargetsUnion() const; inline bool getTargetsGroup() const; inline bool getTargetsInterface() const; inline bool getTargetsMethod() const; inline bool getTargetsParam() const; inline bool getTargetsAnnotation() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Declaration::Annotation::Builder { public: typedef Annotation Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasType(); inline ::capnp::compiler::Expression::Builder getType(); inline void setType( ::capnp::compiler::Expression::Reader value); inline ::capnp::compiler::Expression::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::compiler::Expression>&& value); inline ::capnp::Orphan< ::capnp::compiler::Expression> disownType(); inline bool getTargetsFile(); inline void setTargetsFile(bool value); inline bool getTargetsConst(); inline void setTargetsConst(bool value); inline bool getTargetsEnum(); inline void setTargetsEnum(bool value); inline bool getTargetsEnumerant(); inline void setTargetsEnumerant(bool value); inline bool getTargetsStruct(); inline void setTargetsStruct(bool value); inline bool getTargetsField(); inline void setTargetsField(bool value); inline bool getTargetsUnion(); inline void setTargetsUnion(bool value); inline bool getTargetsGroup(); inline void setTargetsGroup(bool value); inline bool getTargetsInterface(); inline void setTargetsInterface(bool value); inline bool getTargetsMethod(); inline void setTargetsMethod(bool value); inline bool getTargetsParam(); inline void setTargetsParam(bool value); inline bool getTargetsAnnotation(); inline void setTargetsAnnotation(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Declaration::Annotation::Pipeline { public: typedef Annotation Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Expression::Pipeline getType(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class ParsedFile::Reader { public: typedef ParsedFile Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasRoot() const; inline ::capnp::compiler::Declaration::Reader getRoot() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class ParsedFile::Builder { public: typedef ParsedFile Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasRoot(); inline ::capnp::compiler::Declaration::Builder getRoot(); inline void setRoot( ::capnp::compiler::Declaration::Reader value); inline ::capnp::compiler::Declaration::Builder initRoot(); inline void adoptRoot(::capnp::Orphan< ::capnp::compiler::Declaration>&& value); inline ::capnp::Orphan< ::capnp::compiler::Declaration> disownRoot(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class ParsedFile::Pipeline { public: typedef ParsedFile Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::compiler::Declaration::Pipeline getRoot(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline bool LocatedText::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool LocatedText::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader LocatedText::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder LocatedText::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void LocatedText::Builder::setValue( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder LocatedText::Builder::initValue(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void LocatedText::Builder::adoptValue( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> LocatedText::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t LocatedText::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedText::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void LocatedText::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t LocatedText::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedText::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void LocatedText::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint64_t LocatedInteger::Reader::getValue() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t LocatedInteger::Builder::getValue() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void LocatedInteger::Builder::setValue( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t LocatedInteger::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedInteger::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void LocatedInteger::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint32_t LocatedInteger::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedInteger::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline void LocatedInteger::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); } inline double LocatedFloat::Reader::getValue() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline double LocatedFloat::Builder::getValue() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void LocatedFloat::Builder::setValue(double value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t LocatedFloat::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedFloat::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void LocatedFloat::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint32_t LocatedFloat::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint32_t LocatedFloat::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline void LocatedFloat::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); } inline ::capnp::compiler::Expression::Which Expression::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Expression::Which Expression::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Expression::Reader::isUnknown() const { return which() == Expression::UNKNOWN; } inline bool Expression::Builder::isUnknown() { return which() == Expression::UNKNOWN; } inline ::capnp::Void Expression::Reader::getUnknown() const { KJ_IREQUIRE((which() == Expression::UNKNOWN), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Expression::Builder::getUnknown() { KJ_IREQUIRE((which() == Expression::UNKNOWN), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setUnknown( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::UNKNOWN); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Expression::Reader::isPositiveInt() const { return which() == Expression::POSITIVE_INT; } inline bool Expression::Builder::isPositiveInt() { return which() == Expression::POSITIVE_INT; } inline ::uint64_t Expression::Reader::getPositiveInt() const { KJ_IREQUIRE((which() == Expression::POSITIVE_INT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Expression::Builder::getPositiveInt() { KJ_IREQUIRE((which() == Expression::POSITIVE_INT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setPositiveInt( ::uint64_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::POSITIVE_INT); _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Expression::Reader::isNegativeInt() const { return which() == Expression::NEGATIVE_INT; } inline bool Expression::Builder::isNegativeInt() { return which() == Expression::NEGATIVE_INT; } inline ::uint64_t Expression::Reader::getNegativeInt() const { KJ_IREQUIRE((which() == Expression::NEGATIVE_INT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Expression::Builder::getNegativeInt() { KJ_IREQUIRE((which() == Expression::NEGATIVE_INT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setNegativeInt( ::uint64_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::NEGATIVE_INT); _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Expression::Reader::isFloat() const { return which() == Expression::FLOAT; } inline bool Expression::Builder::isFloat() { return which() == Expression::FLOAT; } inline double Expression::Reader::getFloat() const { KJ_IREQUIRE((which() == Expression::FLOAT), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline double Expression::Builder::getFloat() { KJ_IREQUIRE((which() == Expression::FLOAT), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setFloat(double value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::FLOAT); _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Expression::Reader::isString() const { return which() == Expression::STRING; } inline bool Expression::Builder::isString() { return which() == Expression::STRING; } inline bool Expression::Reader::hasString() const { if (which() != Expression::STRING) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasString() { if (which() != Expression::STRING) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Expression::Reader::getString() const { KJ_IREQUIRE((which() == Expression::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Expression::Builder::getString() { KJ_IREQUIRE((which() == Expression::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setString( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Expression::Builder::initString(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Expression::Builder::adoptString( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::STRING); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Expression::Builder::disownString() { KJ_IREQUIRE((which() == Expression::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isRelativeName() const { return which() == Expression::RELATIVE_NAME; } inline bool Expression::Builder::isRelativeName() { return which() == Expression::RELATIVE_NAME; } inline bool Expression::Reader::hasRelativeName() const { if (which() != Expression::RELATIVE_NAME) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasRelativeName() { if (which() != Expression::RELATIVE_NAME) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getRelativeName() const { KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getRelativeName() { KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setRelativeName( ::capnp::compiler::LocatedText::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initRelativeName() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::adoptRelativeName( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::RELATIVE_NAME); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownRelativeName() { KJ_IREQUIRE((which() == Expression::RELATIVE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isList() const { return which() == Expression::LIST; } inline bool Expression::Builder::isList() { return which() == Expression::LIST; } inline bool Expression::Reader::hasList() const { if (which() != Expression::LIST) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasList() { if (which() != Expression::LIST) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader Expression::Reader::getList() const { KJ_IREQUIRE((which() == Expression::LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Expression::Builder::getList() { KJ_IREQUIRE((which() == Expression::LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setList( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Expression::Builder::initList(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Expression::Builder::adoptList( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> Expression::Builder::disownList() { KJ_IREQUIRE((which() == Expression::LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isTuple() const { return which() == Expression::TUPLE; } inline bool Expression::Builder::isTuple() { return which() == Expression::TUPLE; } inline bool Expression::Reader::hasTuple() const { if (which() != Expression::TUPLE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasTuple() { if (which() != Expression::TUPLE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader Expression::Reader::getTuple() const { KJ_IREQUIRE((which() == Expression::TUPLE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Builder::getTuple() { KJ_IREQUIRE((which() == Expression::TUPLE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setTuple( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Builder::initTuple(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Expression::Builder::adoptTuple( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::TUPLE); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> Expression::Builder::disownTuple() { KJ_IREQUIRE((which() == Expression::TUPLE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Expression::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Expression::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Expression::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::uint32_t Expression::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline void Expression::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS, value); } inline bool Expression::Reader::isBinary() const { return which() == Expression::BINARY; } inline bool Expression::Builder::isBinary() { return which() == Expression::BINARY; } inline bool Expression::Reader::hasBinary() const { if (which() != Expression::BINARY) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasBinary() { if (which() != Expression::BINARY) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Data::Reader Expression::Reader::getBinary() const { KJ_IREQUIRE((which() == Expression::BINARY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Data::Builder Expression::Builder::getBinary() { KJ_IREQUIRE((which() == Expression::BINARY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setBinary( ::capnp::Data::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Data::Builder Expression::Builder::initBinary(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Expression::Builder::adoptBinary( ::capnp::Orphan< ::capnp::Data>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::BINARY); ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Data> Expression::Builder::disownBinary() { KJ_IREQUIRE((which() == Expression::BINARY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isApplication() const { return which() == Expression::APPLICATION; } inline bool Expression::Builder::isApplication() { return which() == Expression::APPLICATION; } inline typename Expression::Application::Reader Expression::Reader::getApplication() const { KJ_IREQUIRE((which() == Expression::APPLICATION), "Must check which() before get()ing a union member."); return typename Expression::Application::Reader(_reader); } inline typename Expression::Application::Builder Expression::Builder::getApplication() { KJ_IREQUIRE((which() == Expression::APPLICATION), "Must check which() before get()ing a union member."); return typename Expression::Application::Builder(_builder); } inline typename Expression::Application::Builder Expression::Builder::initApplication() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::APPLICATION); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); return typename Expression::Application::Builder(_builder); } inline bool Expression::Reader::isMember() const { return which() == Expression::MEMBER; } inline bool Expression::Builder::isMember() { return which() == Expression::MEMBER; } inline typename Expression::Member::Reader Expression::Reader::getMember() const { KJ_IREQUIRE((which() == Expression::MEMBER), "Must check which() before get()ing a union member."); return typename Expression::Member::Reader(_reader); } inline typename Expression::Member::Builder Expression::Builder::getMember() { KJ_IREQUIRE((which() == Expression::MEMBER), "Must check which() before get()ing a union member."); return typename Expression::Member::Builder(_builder); } inline typename Expression::Member::Builder Expression::Builder::initMember() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::MEMBER); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); return typename Expression::Member::Builder(_builder); } inline bool Expression::Reader::isAbsoluteName() const { return which() == Expression::ABSOLUTE_NAME; } inline bool Expression::Builder::isAbsoluteName() { return which() == Expression::ABSOLUTE_NAME; } inline bool Expression::Reader::hasAbsoluteName() const { if (which() != Expression::ABSOLUTE_NAME) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasAbsoluteName() { if (which() != Expression::ABSOLUTE_NAME) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getAbsoluteName() const { KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getAbsoluteName() { KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setAbsoluteName( ::capnp::compiler::LocatedText::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initAbsoluteName() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::adoptAbsoluteName( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::ABSOLUTE_NAME); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownAbsoluteName() { KJ_IREQUIRE((which() == Expression::ABSOLUTE_NAME), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isImport() const { return which() == Expression::IMPORT; } inline bool Expression::Builder::isImport() { return which() == Expression::IMPORT; } inline bool Expression::Reader::hasImport() const { if (which() != Expression::IMPORT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasImport() { if (which() != Expression::IMPORT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getImport() const { KJ_IREQUIRE((which() == Expression::IMPORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getImport() { KJ_IREQUIRE((which() == Expression::IMPORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setImport( ::capnp::compiler::LocatedText::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initImport() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::adoptImport( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::IMPORT); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownImport() { KJ_IREQUIRE((which() == Expression::IMPORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Reader::isEmbed() const { return which() == Expression::EMBED; } inline bool Expression::Builder::isEmbed() { return which() == Expression::EMBED; } inline bool Expression::Reader::hasEmbed() const { if (which() != Expression::EMBED) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Builder::hasEmbed() { if (which() != Expression::EMBED) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Reader::getEmbed() const { KJ_IREQUIRE((which() == Expression::EMBED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::getEmbed() { KJ_IREQUIRE((which() == Expression::EMBED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::setEmbed( ::capnp::compiler::LocatedText::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Builder::initEmbed() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Builder::adoptEmbed( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::EMBED); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Builder::disownEmbed() { KJ_IREQUIRE((which() == Expression::EMBED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Param::Which Expression::Param::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Expression::Param::Which Expression::Param::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Expression::Param::Reader::isUnnamed() const { return which() == Expression::Param::UNNAMED; } inline bool Expression::Param::Builder::isUnnamed() { return which() == Expression::Param::UNNAMED; } inline ::capnp::Void Expression::Param::Reader::getUnnamed() const { KJ_IREQUIRE((which() == Expression::Param::UNNAMED), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Expression::Param::Builder::getUnnamed() { KJ_IREQUIRE((which() == Expression::Param::UNNAMED), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Expression::Param::Builder::setUnnamed( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::UNNAMED); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Expression::Param::Reader::isNamed() const { return which() == Expression::Param::NAMED; } inline bool Expression::Param::Builder::isNamed() { return which() == Expression::Param::NAMED; } inline bool Expression::Param::Reader::hasNamed() const { if (which() != Expression::Param::NAMED) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Param::Builder::hasNamed() { if (which() != Expression::Param::NAMED) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Param::Reader::getNamed() const { KJ_IREQUIRE((which() == Expression::Param::NAMED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Param::Builder::getNamed() { KJ_IREQUIRE((which() == Expression::Param::NAMED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Param::Builder::setNamed( ::capnp::compiler::LocatedText::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Param::Builder::initNamed() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Param::Builder::adoptNamed( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Expression::Param::NAMED); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Param::Builder::disownNamed() { KJ_IREQUIRE((which() == Expression::Param::NAMED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Param::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Param::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Expression::Param::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Expression::Param::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Expression::Param::Pipeline::getValue() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Expression::Param::Builder::setValue( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Expression::Param::Builder::initValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Expression::Param::Builder::adoptValue( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Param::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Expression::Application::Reader::hasFunction() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Application::Builder::hasFunction() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Expression::Application::Reader::getFunction() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Expression::Application::Builder::getFunction() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Expression::Application::Pipeline::getFunction() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Expression::Application::Builder::setFunction( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Expression::Application::Builder::initFunction() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Application::Builder::adoptFunction( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Application::Builder::disownFunction() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Application::Reader::hasParams() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Application::Builder::hasParams() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader Expression::Application::Reader::getParams() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Application::Builder::getParams() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Expression::Application::Builder::setParams( ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>::Builder Expression::Application::Builder::initParams(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Expression::Application::Builder::adoptParams( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>> Expression::Application::Builder::disownParams() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Expression::Member::Reader::hasParent() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Member::Builder::hasParent() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Expression::Member::Reader::getParent() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Expression::Member::Builder::getParent() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Expression::Member::Pipeline::getParent() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Expression::Member::Builder::setParent( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Expression::Member::Builder::initParent() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Expression::Member::Builder::adoptParent( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Expression::Member::Builder::disownParent() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Expression::Member::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Expression::Member::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Expression::Member::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Expression::Member::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::LocatedText::Pipeline Expression::Member::Pipeline::getName() { return ::capnp::compiler::LocatedText::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Expression::Member::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Expression::Member::Builder::initName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Expression::Member::Builder::adoptName( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Expression::Member::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::Which Declaration::Reader::which() const { return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::Which Declaration::Builder::which() { return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline bool Declaration::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Declaration::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Declaration::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::LocatedText::Pipeline Declaration::Pipeline::getName() { return ::capnp::compiler::LocatedText::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Declaration::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Declaration::Builder::initName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::Builder::adoptName( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Declaration::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline typename Declaration::Id::Reader Declaration::Reader::getId() const { return typename Declaration::Id::Reader(_reader); } inline typename Declaration::Id::Builder Declaration::Builder::getId() { return typename Declaration::Id::Builder(_builder); } #if !CAPNP_LITE inline typename Declaration::Id::Pipeline Declaration::Pipeline::getId() { return typename Declaration::Id::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Declaration::Id::Builder Declaration::Builder::initId() { _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); return typename Declaration::Id::Builder(_builder); } inline bool Declaration::Reader::hasNestedDecls() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasNestedDecls() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getNestedDecls() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getNestedDecls() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setNestedDecls( ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initNestedDecls(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), size); } inline void Declaration::Builder::adoptNestedDecls( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>> Declaration::Builder::disownNestedDecls() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline bool Declaration::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), size); } inline void Declaration::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> Declaration::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::uint32_t Declaration::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Declaration::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::hasDocComment() const { return !_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasDocComment() { return !_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Declaration::Reader::getDocComment() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Declaration::Builder::getDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setDocComment( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Declaration::Builder::initDocComment(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), size); } inline void Declaration::Builder::adoptDocComment( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Declaration::Builder::disownDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline bool Declaration::Reader::isFile() const { return which() == Declaration::FILE; } inline bool Declaration::Builder::isFile() { return which() == Declaration::FILE; } inline ::capnp::Void Declaration::Reader::getFile() const { KJ_IREQUIRE((which() == Declaration::FILE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getFile() { KJ_IREQUIRE((which() == Declaration::FILE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setFile( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::FILE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isUsing() const { return which() == Declaration::USING; } inline bool Declaration::Builder::isUsing() { return which() == Declaration::USING; } inline typename Declaration::Using::Reader Declaration::Reader::getUsing() const { KJ_IREQUIRE((which() == Declaration::USING), "Must check which() before get()ing a union member."); return typename Declaration::Using::Reader(_reader); } inline typename Declaration::Using::Builder Declaration::Builder::getUsing() { KJ_IREQUIRE((which() == Declaration::USING), "Must check which() before get()ing a union member."); return typename Declaration::Using::Builder(_builder); } inline typename Declaration::Using::Builder Declaration::Builder::initUsing() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::USING); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); return typename Declaration::Using::Builder(_builder); } inline bool Declaration::Reader::isConst() const { return which() == Declaration::CONST; } inline bool Declaration::Builder::isConst() { return which() == Declaration::CONST; } inline typename Declaration::Const::Reader Declaration::Reader::getConst() const { KJ_IREQUIRE((which() == Declaration::CONST), "Must check which() before get()ing a union member."); return typename Declaration::Const::Reader(_reader); } inline typename Declaration::Const::Builder Declaration::Builder::getConst() { KJ_IREQUIRE((which() == Declaration::CONST), "Must check which() before get()ing a union member."); return typename Declaration::Const::Builder(_builder); } inline typename Declaration::Const::Builder Declaration::Builder::initConst() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::CONST); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); return typename Declaration::Const::Builder(_builder); } inline bool Declaration::Reader::isEnum() const { return which() == Declaration::ENUM; } inline bool Declaration::Builder::isEnum() { return which() == Declaration::ENUM; } inline ::capnp::Void Declaration::Reader::getEnum() const { KJ_IREQUIRE((which() == Declaration::ENUM), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getEnum() { KJ_IREQUIRE((which() == Declaration::ENUM), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setEnum( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ENUM); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isEnumerant() const { return which() == Declaration::ENUMERANT; } inline bool Declaration::Builder::isEnumerant() { return which() == Declaration::ENUMERANT; } inline ::capnp::Void Declaration::Reader::getEnumerant() const { KJ_IREQUIRE((which() == Declaration::ENUMERANT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getEnumerant() { KJ_IREQUIRE((which() == Declaration::ENUMERANT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setEnumerant( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ENUMERANT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isStruct() const { return which() == Declaration::STRUCT; } inline bool Declaration::Builder::isStruct() { return which() == Declaration::STRUCT; } inline ::capnp::Void Declaration::Reader::getStruct() const { KJ_IREQUIRE((which() == Declaration::STRUCT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getStruct() { KJ_IREQUIRE((which() == Declaration::STRUCT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setStruct( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::STRUCT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isField() const { return which() == Declaration::FIELD; } inline bool Declaration::Builder::isField() { return which() == Declaration::FIELD; } inline typename Declaration::Field::Reader Declaration::Reader::getField() const { KJ_IREQUIRE((which() == Declaration::FIELD), "Must check which() before get()ing a union member."); return typename Declaration::Field::Reader(_reader); } inline typename Declaration::Field::Builder Declaration::Builder::getField() { KJ_IREQUIRE((which() == Declaration::FIELD), "Must check which() before get()ing a union member."); return typename Declaration::Field::Builder(_builder); } inline typename Declaration::Field::Builder Declaration::Builder::initField() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::FIELD); _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); return typename Declaration::Field::Builder(_builder); } inline bool Declaration::Reader::isUnion() const { return which() == Declaration::UNION; } inline bool Declaration::Builder::isUnion() { return which() == Declaration::UNION; } inline ::capnp::Void Declaration::Reader::getUnion() const { KJ_IREQUIRE((which() == Declaration::UNION), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getUnion() { KJ_IREQUIRE((which() == Declaration::UNION), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setUnion( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::UNION); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isGroup() const { return which() == Declaration::GROUP; } inline bool Declaration::Builder::isGroup() { return which() == Declaration::GROUP; } inline ::capnp::Void Declaration::Reader::getGroup() const { KJ_IREQUIRE((which() == Declaration::GROUP), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getGroup() { KJ_IREQUIRE((which() == Declaration::GROUP), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setGroup( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::GROUP); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isInterface() const { return which() == Declaration::INTERFACE; } inline bool Declaration::Builder::isInterface() { return which() == Declaration::INTERFACE; } inline typename Declaration::Interface::Reader Declaration::Reader::getInterface() const { KJ_IREQUIRE((which() == Declaration::INTERFACE), "Must check which() before get()ing a union member."); return typename Declaration::Interface::Reader(_reader); } inline typename Declaration::Interface::Builder Declaration::Builder::getInterface() { KJ_IREQUIRE((which() == Declaration::INTERFACE), "Must check which() before get()ing a union member."); return typename Declaration::Interface::Builder(_builder); } inline typename Declaration::Interface::Builder Declaration::Builder::initInterface() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::INTERFACE); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); return typename Declaration::Interface::Builder(_builder); } inline bool Declaration::Reader::isMethod() const { return which() == Declaration::METHOD; } inline bool Declaration::Builder::isMethod() { return which() == Declaration::METHOD; } inline typename Declaration::Method::Reader Declaration::Reader::getMethod() const { KJ_IREQUIRE((which() == Declaration::METHOD), "Must check which() before get()ing a union member."); return typename Declaration::Method::Reader(_reader); } inline typename Declaration::Method::Builder Declaration::Builder::getMethod() { KJ_IREQUIRE((which() == Declaration::METHOD), "Must check which() before get()ing a union member."); return typename Declaration::Method::Builder(_builder); } inline typename Declaration::Method::Builder Declaration::Builder::initMethod() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::METHOD); _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); return typename Declaration::Method::Builder(_builder); } inline bool Declaration::Reader::isAnnotation() const { return which() == Declaration::ANNOTATION; } inline bool Declaration::Builder::isAnnotation() { return which() == Declaration::ANNOTATION; } inline typename Declaration::Annotation::Reader Declaration::Reader::getAnnotation() const { KJ_IREQUIRE((which() == Declaration::ANNOTATION), "Must check which() before get()ing a union member."); return typename Declaration::Annotation::Reader(_reader); } inline typename Declaration::Annotation::Builder Declaration::Builder::getAnnotation() { KJ_IREQUIRE((which() == Declaration::ANNOTATION), "Must check which() before get()ing a union member."); return typename Declaration::Annotation::Builder(_builder); } inline typename Declaration::Annotation::Builder Declaration::Builder::initAnnotation() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::ANNOTATION); _builder.setDataField(::capnp::bounded<96>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<97>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<98>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<99>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<100>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<101>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<102>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<103>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<104>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<105>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<106>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<107>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); return typename Declaration::Annotation::Builder(_builder); } inline bool Declaration::Reader::isNakedId() const { return which() == Declaration::NAKED_ID; } inline bool Declaration::Builder::isNakedId() { return which() == Declaration::NAKED_ID; } inline bool Declaration::Reader::hasNakedId() const { if (which() != Declaration::NAKED_ID) return false; return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasNakedId() { if (which() != Declaration::NAKED_ID) return false; return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedInteger::Reader Declaration::Reader::getNakedId() const { KJ_IREQUIRE((which() == Declaration::NAKED_ID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Builder::getNakedId() { KJ_IREQUIRE((which() == Declaration::NAKED_ID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setNakedId( ::capnp::compiler::LocatedInteger::Reader value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Builder::initNakedId() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Builder::adoptNakedId( ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ID); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Builder::disownNakedId() { KJ_IREQUIRE((which() == Declaration::NAKED_ID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Reader::isNakedAnnotation() const { return which() == Declaration::NAKED_ANNOTATION; } inline bool Declaration::Builder::isNakedAnnotation() { return which() == Declaration::NAKED_ANNOTATION; } inline bool Declaration::Reader::hasNakedAnnotation() const { if (which() != Declaration::NAKED_ANNOTATION) return false; return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasNakedAnnotation() { if (which() != Declaration::NAKED_ANNOTATION) return false; return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Declaration::AnnotationApplication::Reader Declaration::Reader::getNakedAnnotation() const { KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::AnnotationApplication::Builder Declaration::Builder::getNakedAnnotation() { KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setNakedAnnotation( ::capnp::compiler::Declaration::AnnotationApplication::Reader value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Declaration::AnnotationApplication::Builder Declaration::Builder::initNakedAnnotation() { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Builder::adoptNakedAnnotation( ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication>&& value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::NAKED_ANNOTATION); ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Declaration::AnnotationApplication> Declaration::Builder::disownNakedAnnotation() { KJ_IREQUIRE((which() == Declaration::NAKED_ANNOTATION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::AnnotationApplication>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Reader::isBuiltinVoid() const { return which() == Declaration::BUILTIN_VOID; } inline bool Declaration::Builder::isBuiltinVoid() { return which() == Declaration::BUILTIN_VOID; } inline ::capnp::Void Declaration::Reader::getBuiltinVoid() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_VOID), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinVoid() { KJ_IREQUIRE((which() == Declaration::BUILTIN_VOID), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinVoid( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_VOID); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinBool() const { return which() == Declaration::BUILTIN_BOOL; } inline bool Declaration::Builder::isBuiltinBool() { return which() == Declaration::BUILTIN_BOOL; } inline ::capnp::Void Declaration::Reader::getBuiltinBool() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_BOOL), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinBool() { KJ_IREQUIRE((which() == Declaration::BUILTIN_BOOL), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinBool( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_BOOL); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinInt8() const { return which() == Declaration::BUILTIN_INT8; } inline bool Declaration::Builder::isBuiltinInt8() { return which() == Declaration::BUILTIN_INT8; } inline ::capnp::Void Declaration::Reader::getBuiltinInt8() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinInt8() { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinInt8( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT8); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinInt16() const { return which() == Declaration::BUILTIN_INT16; } inline bool Declaration::Builder::isBuiltinInt16() { return which() == Declaration::BUILTIN_INT16; } inline ::capnp::Void Declaration::Reader::getBuiltinInt16() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinInt16() { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinInt16( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT16); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinInt32() const { return which() == Declaration::BUILTIN_INT32; } inline bool Declaration::Builder::isBuiltinInt32() { return which() == Declaration::BUILTIN_INT32; } inline ::capnp::Void Declaration::Reader::getBuiltinInt32() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinInt32() { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinInt32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinInt64() const { return which() == Declaration::BUILTIN_INT64; } inline bool Declaration::Builder::isBuiltinInt64() { return which() == Declaration::BUILTIN_INT64; } inline ::capnp::Void Declaration::Reader::getBuiltinInt64() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinInt64() { KJ_IREQUIRE((which() == Declaration::BUILTIN_INT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinInt64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_INT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinUInt8() const { return which() == Declaration::BUILTIN_U_INT8; } inline bool Declaration::Builder::isBuiltinUInt8() { return which() == Declaration::BUILTIN_U_INT8; } inline ::capnp::Void Declaration::Reader::getBuiltinUInt8() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinUInt8() { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinUInt8( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT8); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinUInt16() const { return which() == Declaration::BUILTIN_U_INT16; } inline bool Declaration::Builder::isBuiltinUInt16() { return which() == Declaration::BUILTIN_U_INT16; } inline ::capnp::Void Declaration::Reader::getBuiltinUInt16() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinUInt16() { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinUInt16( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT16); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinUInt32() const { return which() == Declaration::BUILTIN_U_INT32; } inline bool Declaration::Builder::isBuiltinUInt32() { return which() == Declaration::BUILTIN_U_INT32; } inline ::capnp::Void Declaration::Reader::getBuiltinUInt32() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinUInt32() { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinUInt32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinUInt64() const { return which() == Declaration::BUILTIN_U_INT64; } inline bool Declaration::Builder::isBuiltinUInt64() { return which() == Declaration::BUILTIN_U_INT64; } inline ::capnp::Void Declaration::Reader::getBuiltinUInt64() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinUInt64() { KJ_IREQUIRE((which() == Declaration::BUILTIN_U_INT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinUInt64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_U_INT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinFloat32() const { return which() == Declaration::BUILTIN_FLOAT32; } inline bool Declaration::Builder::isBuiltinFloat32() { return which() == Declaration::BUILTIN_FLOAT32; } inline ::capnp::Void Declaration::Reader::getBuiltinFloat32() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinFloat32() { KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinFloat32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_FLOAT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinFloat64() const { return which() == Declaration::BUILTIN_FLOAT64; } inline bool Declaration::Builder::isBuiltinFloat64() { return which() == Declaration::BUILTIN_FLOAT64; } inline ::capnp::Void Declaration::Reader::getBuiltinFloat64() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinFloat64() { KJ_IREQUIRE((which() == Declaration::BUILTIN_FLOAT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinFloat64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_FLOAT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinText() const { return which() == Declaration::BUILTIN_TEXT; } inline bool Declaration::Builder::isBuiltinText() { return which() == Declaration::BUILTIN_TEXT; } inline ::capnp::Void Declaration::Reader::getBuiltinText() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_TEXT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinText() { KJ_IREQUIRE((which() == Declaration::BUILTIN_TEXT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinText( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_TEXT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinData() const { return which() == Declaration::BUILTIN_DATA; } inline bool Declaration::Builder::isBuiltinData() { return which() == Declaration::BUILTIN_DATA; } inline ::capnp::Void Declaration::Reader::getBuiltinData() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_DATA), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinData() { KJ_IREQUIRE((which() == Declaration::BUILTIN_DATA), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinData( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_DATA); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinList() const { return which() == Declaration::BUILTIN_LIST; } inline bool Declaration::Builder::isBuiltinList() { return which() == Declaration::BUILTIN_LIST; } inline ::capnp::Void Declaration::Reader::getBuiltinList() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_LIST), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinList() { KJ_IREQUIRE((which() == Declaration::BUILTIN_LIST), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinList( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_LIST); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinObject() const { return which() == Declaration::BUILTIN_OBJECT; } inline bool Declaration::Builder::isBuiltinObject() { return which() == Declaration::BUILTIN_OBJECT; } inline ::capnp::Void Declaration::Reader::getBuiltinObject() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_OBJECT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinObject() { KJ_IREQUIRE((which() == Declaration::BUILTIN_OBJECT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinObject( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_OBJECT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinAnyPointer() const { return which() == Declaration::BUILTIN_ANY_POINTER; } inline bool Declaration::Builder::isBuiltinAnyPointer() { return which() == Declaration::BUILTIN_ANY_POINTER; } inline ::capnp::Void Declaration::Reader::getBuiltinAnyPointer() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_POINTER), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinAnyPointer() { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_POINTER), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinAnyPointer( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_POINTER); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::hasParameters() const { return !_reader.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Builder::hasParameters() { return !_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader Declaration::Reader::getParameters() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::getParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS)); } inline void Declaration::Builder::setParameters( ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>::Builder Declaration::Builder::initParameters(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS), size); } inline void Declaration::Builder::adoptParameters( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>> Declaration::Builder::disownParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::BrandParameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<7>() * ::capnp::POINTERS)); } inline bool Declaration::Reader::isBuiltinAnyStruct() const { return which() == Declaration::BUILTIN_ANY_STRUCT; } inline bool Declaration::Builder::isBuiltinAnyStruct() { return which() == Declaration::BUILTIN_ANY_STRUCT; } inline ::capnp::Void Declaration::Reader::getBuiltinAnyStruct() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_STRUCT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinAnyStruct() { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_STRUCT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinAnyStruct( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_STRUCT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinAnyList() const { return which() == Declaration::BUILTIN_ANY_LIST; } inline bool Declaration::Builder::isBuiltinAnyList() { return which() == Declaration::BUILTIN_ANY_LIST; } inline ::capnp::Void Declaration::Reader::getBuiltinAnyList() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_LIST), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinAnyList() { KJ_IREQUIRE((which() == Declaration::BUILTIN_ANY_LIST), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinAnyList( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_ANY_LIST); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Reader::isBuiltinCapability() const { return which() == Declaration::BUILTIN_CAPABILITY; } inline bool Declaration::Builder::isBuiltinCapability() { return which() == Declaration::BUILTIN_CAPABILITY; } inline ::capnp::Void Declaration::Reader::getBuiltinCapability() const { KJ_IREQUIRE((which() == Declaration::BUILTIN_CAPABILITY), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Builder::getBuiltinCapability() { KJ_IREQUIRE((which() == Declaration::BUILTIN_CAPABILITY), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Builder::setBuiltinCapability( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, Declaration::BUILTIN_CAPABILITY); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::BrandParameter::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::BrandParameter::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Declaration::BrandParameter::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Declaration::BrandParameter::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::BrandParameter::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Declaration::BrandParameter::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Declaration::BrandParameter::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Declaration::BrandParameter::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Declaration::BrandParameter::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::BrandParameter::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::BrandParameter::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Declaration::BrandParameter::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::BrandParameter::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Declaration::BrandParameter::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Declaration::AnnotationApplication::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::AnnotationApplication::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::AnnotationApplication::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::AnnotationApplication::Pipeline::getName() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Declaration::AnnotationApplication::Builder::setName( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Builder::initName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::AnnotationApplication::Builder::adoptName( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::AnnotationApplication::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline typename Declaration::AnnotationApplication::Value::Reader Declaration::AnnotationApplication::Reader::getValue() const { return typename Declaration::AnnotationApplication::Value::Reader(_reader); } inline typename Declaration::AnnotationApplication::Value::Builder Declaration::AnnotationApplication::Builder::getValue() { return typename Declaration::AnnotationApplication::Value::Builder(_builder); } #if !CAPNP_LITE inline typename Declaration::AnnotationApplication::Value::Pipeline Declaration::AnnotationApplication::Pipeline::getValue() { return typename Declaration::AnnotationApplication::Value::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Declaration::AnnotationApplication::Value::Builder Declaration::AnnotationApplication::Builder::initValue() { _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<1>() * ::capnp::POINTERS).clear(); return typename Declaration::AnnotationApplication::Value::Builder(_builder); } inline ::capnp::compiler::Declaration::AnnotationApplication::Value::Which Declaration::AnnotationApplication::Value::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::AnnotationApplication::Value::Which Declaration::AnnotationApplication::Value::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Declaration::AnnotationApplication::Value::Reader::isNone() const { return which() == Declaration::AnnotationApplication::Value::NONE; } inline bool Declaration::AnnotationApplication::Value::Builder::isNone() { return which() == Declaration::AnnotationApplication::Value::NONE; } inline ::capnp::Void Declaration::AnnotationApplication::Value::Reader::getNone() const { KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::NONE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::AnnotationApplication::Value::Builder::getNone() { KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::NONE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::AnnotationApplication::Value::Builder::setNone( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::NONE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::AnnotationApplication::Value::Reader::isExpression() const { return which() == Declaration::AnnotationApplication::Value::EXPRESSION; } inline bool Declaration::AnnotationApplication::Value::Builder::isExpression() { return which() == Declaration::AnnotationApplication::Value::EXPRESSION; } inline bool Declaration::AnnotationApplication::Value::Reader::hasExpression() const { if (which() != Declaration::AnnotationApplication::Value::EXPRESSION) return false; return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::AnnotationApplication::Value::Builder::hasExpression() { if (which() != Declaration::AnnotationApplication::Value::EXPRESSION) return false; return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::AnnotationApplication::Value::Reader::getExpression() const { KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Value::Builder::getExpression() { KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::AnnotationApplication::Value::Builder::setExpression( ::capnp::compiler::Expression::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::AnnotationApplication::Value::Builder::initExpression() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::AnnotationApplication::Value::Builder::adoptExpression( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::AnnotationApplication::Value::EXPRESSION); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::AnnotationApplication::Value::Builder::disownExpression() { KJ_IREQUIRE((which() == Declaration::AnnotationApplication::Value::EXPRESSION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::ParamList::Which Declaration::ParamList::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::ParamList::Which Declaration::ParamList::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Declaration::ParamList::Reader::isNamedList() const { return which() == Declaration::ParamList::NAMED_LIST; } inline bool Declaration::ParamList::Builder::isNamedList() { return which() == Declaration::ParamList::NAMED_LIST; } inline bool Declaration::ParamList::Reader::hasNamedList() const { if (which() != Declaration::ParamList::NAMED_LIST) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::ParamList::Builder::hasNamedList() { if (which() != Declaration::ParamList::NAMED_LIST) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader Declaration::ParamList::Reader::getNamedList() const { KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder Declaration::ParamList::Builder::getNamedList() { KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::ParamList::Builder::setNamedList( ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>::Builder Declaration::ParamList::Builder::initNamedList(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Declaration::ParamList::Builder::adoptNamedList( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::NAMED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>> Declaration::ParamList::Builder::disownNamedList() { KJ_IREQUIRE((which() == Declaration::ParamList::NAMED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::Param, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Declaration::ParamList::Reader::isType() const { return which() == Declaration::ParamList::TYPE; } inline bool Declaration::ParamList::Builder::isType() { return which() == Declaration::ParamList::TYPE; } inline bool Declaration::ParamList::Reader::hasType() const { if (which() != Declaration::ParamList::TYPE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::ParamList::Builder::hasType() { if (which() != Declaration::ParamList::TYPE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::ParamList::Reader::getType() const { KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::ParamList::Builder::getType() { KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::ParamList::Builder::setType( ::capnp::compiler::Expression::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::ParamList::Builder::initType() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::ParamList::Builder::adoptType( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::TYPE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::ParamList::Builder::disownType() { KJ_IREQUIRE((which() == Declaration::ParamList::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Declaration::ParamList::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::ParamList::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Declaration::ParamList::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Declaration::ParamList::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::ParamList::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Declaration::ParamList::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Declaration::ParamList::Reader::isStream() const { return which() == Declaration::ParamList::STREAM; } inline bool Declaration::ParamList::Builder::isStream() { return which() == Declaration::ParamList::STREAM; } inline ::capnp::Void Declaration::ParamList::Reader::getStream() const { KJ_IREQUIRE((which() == Declaration::ParamList::STREAM), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::ParamList::Builder::getStream() { KJ_IREQUIRE((which() == Declaration::ParamList::STREAM), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::ParamList::Builder::setStream( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::ParamList::STREAM); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Param::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Param::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedText::Reader Declaration::Param::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedText::Builder Declaration::Param::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::LocatedText::Pipeline Declaration::Param::Pipeline::getName() { return ::capnp::compiler::LocatedText::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Declaration::Param::Builder::setName( ::capnp::compiler::LocatedText::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedText::Builder Declaration::Param::Builder::initName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Declaration::Param::Builder::adoptName( ::capnp::Orphan< ::capnp::compiler::LocatedText>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedText> Declaration::Param::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedText>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Declaration::Param::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Param::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Param::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Param::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Param::Pipeline::getType() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Declaration::Param::Builder::setType( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Param::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::Param::Builder::adoptType( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Param::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Declaration::Param::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Param::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader Declaration::Param::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Param::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Declaration::Param::Builder::setAnnotations( ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>::Builder Declaration::Param::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), size); } inline void Declaration::Param::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>> Declaration::Param::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Declaration::AnnotationApplication, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline typename Declaration::Param::DefaultValue::Reader Declaration::Param::Reader::getDefaultValue() const { return typename Declaration::Param::DefaultValue::Reader(_reader); } inline typename Declaration::Param::DefaultValue::Builder Declaration::Param::Builder::getDefaultValue() { return typename Declaration::Param::DefaultValue::Builder(_builder); } #if !CAPNP_LITE inline typename Declaration::Param::DefaultValue::Pipeline Declaration::Param::Pipeline::getDefaultValue() { return typename Declaration::Param::DefaultValue::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Declaration::Param::DefaultValue::Builder Declaration::Param::Builder::initDefaultValue() { _builder.setDataField< ::uint16_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); return typename Declaration::Param::DefaultValue::Builder(_builder); } inline ::uint32_t Declaration::Param::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::Param::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Declaration::Param::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Declaration::Param::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Declaration::Param::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Declaration::Param::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::capnp::compiler::Declaration::Param::DefaultValue::Which Declaration::Param::DefaultValue::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::Param::DefaultValue::Which Declaration::Param::DefaultValue::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Declaration::Param::DefaultValue::Reader::isNone() const { return which() == Declaration::Param::DefaultValue::NONE; } inline bool Declaration::Param::DefaultValue::Builder::isNone() { return which() == Declaration::Param::DefaultValue::NONE; } inline ::capnp::Void Declaration::Param::DefaultValue::Reader::getNone() const { KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::NONE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Param::DefaultValue::Builder::getNone() { KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::NONE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Param::DefaultValue::Builder::setNone( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::NONE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Param::DefaultValue::Reader::isValue() const { return which() == Declaration::Param::DefaultValue::VALUE; } inline bool Declaration::Param::DefaultValue::Builder::isValue() { return which() == Declaration::Param::DefaultValue::VALUE; } inline bool Declaration::Param::DefaultValue::Reader::hasValue() const { if (which() != Declaration::Param::DefaultValue::VALUE) return false; return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Param::DefaultValue::Builder::hasValue() { if (which() != Declaration::Param::DefaultValue::VALUE) return false; return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Param::DefaultValue::Reader::getValue() const { KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Param::DefaultValue::Builder::getValue() { KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Declaration::Param::DefaultValue::Builder::setValue( ::capnp::compiler::Expression::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Param::DefaultValue::Builder::initValue() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Declaration::Param::DefaultValue::Builder::adoptValue( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Param::DefaultValue::VALUE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Param::DefaultValue::Builder::disownValue() { KJ_IREQUIRE((which() == Declaration::Param::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::Id::Which Declaration::Id::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::Id::Which Declaration::Id::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Declaration::Id::Reader::isUnspecified() const { return which() == Declaration::Id::UNSPECIFIED; } inline bool Declaration::Id::Builder::isUnspecified() { return which() == Declaration::Id::UNSPECIFIED; } inline ::capnp::Void Declaration::Id::Reader::getUnspecified() const { KJ_IREQUIRE((which() == Declaration::Id::UNSPECIFIED), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Id::Builder::getUnspecified() { KJ_IREQUIRE((which() == Declaration::Id::UNSPECIFIED), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Id::Builder::setUnspecified( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UNSPECIFIED); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Id::Reader::isUid() const { return which() == Declaration::Id::UID; } inline bool Declaration::Id::Builder::isUid() { return which() == Declaration::Id::UID; } inline bool Declaration::Id::Reader::hasUid() const { if (which() != Declaration::Id::UID) return false; return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Id::Builder::hasUid() { if (which() != Declaration::Id::UID) return false; return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedInteger::Reader Declaration::Id::Reader::getUid() const { KJ_IREQUIRE((which() == Declaration::Id::UID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::getUid() { KJ_IREQUIRE((which() == Declaration::Id::UID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::Id::Builder::setUid( ::capnp::compiler::LocatedInteger::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::initUid() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::Id::Builder::adoptUid( ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::UID); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Id::Builder::disownUid() { KJ_IREQUIRE((which() == Declaration::Id::UID), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Declaration::Id::Reader::isOrdinal() const { return which() == Declaration::Id::ORDINAL; } inline bool Declaration::Id::Builder::isOrdinal() { return which() == Declaration::Id::ORDINAL; } inline bool Declaration::Id::Reader::hasOrdinal() const { if (which() != Declaration::Id::ORDINAL) return false; return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Id::Builder::hasOrdinal() { if (which() != Declaration::Id::ORDINAL) return false; return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::LocatedInteger::Reader Declaration::Id::Reader::getOrdinal() const { KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::getOrdinal() { KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::Id::Builder::setOrdinal( ::capnp::compiler::LocatedInteger::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::LocatedInteger::Builder Declaration::Id::Builder::initOrdinal() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Declaration::Id::Builder::adoptOrdinal( ::capnp::Orphan< ::capnp::compiler::LocatedInteger>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Declaration::Id::ORDINAL); ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::LocatedInteger> Declaration::Id::Builder::disownOrdinal() { KJ_IREQUIRE((which() == Declaration::Id::ORDINAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::LocatedInteger>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Declaration::Using::Reader::hasTarget() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Using::Builder::hasTarget() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Using::Reader::getTarget() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Using::Builder::getTarget() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Using::Pipeline::getTarget() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(5)); } #endif // !CAPNP_LITE inline void Declaration::Using::Builder::setTarget( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Using::Builder::initTarget() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Using::Builder::adoptTarget( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Using::Builder::disownTarget() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Const::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Const::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Const::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Const::Pipeline::getType() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(5)); } #endif // !CAPNP_LITE inline void Declaration::Const::Builder::setType( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Const::Builder::adoptType( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Const::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Const::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Const::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Const::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Const::Pipeline::getValue() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(6)); } #endif // !CAPNP_LITE inline void Declaration::Const::Builder::setValue( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Const::Builder::initValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline void Declaration::Const::Builder::adoptValue( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Const::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline bool Declaration::Field::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Field::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Field::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Field::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Field::Pipeline::getType() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(5)); } #endif // !CAPNP_LITE inline void Declaration::Field::Builder::setType( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Field::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Field::Builder::adoptType( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Field::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline typename Declaration::Field::DefaultValue::Reader Declaration::Field::Reader::getDefaultValue() const { return typename Declaration::Field::DefaultValue::Reader(_reader); } inline typename Declaration::Field::DefaultValue::Builder Declaration::Field::Builder::getDefaultValue() { return typename Declaration::Field::DefaultValue::Builder(_builder); } #if !CAPNP_LITE inline typename Declaration::Field::DefaultValue::Pipeline Declaration::Field::Pipeline::getDefaultValue() { return typename Declaration::Field::DefaultValue::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Declaration::Field::DefaultValue::Builder Declaration::Field::Builder::initDefaultValue() { _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); return typename Declaration::Field::DefaultValue::Builder(_builder); } inline ::capnp::compiler::Declaration::Field::DefaultValue::Which Declaration::Field::DefaultValue::Reader::which() const { return _reader.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::Field::DefaultValue::Which Declaration::Field::DefaultValue::Builder::which() { return _builder.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline bool Declaration::Field::DefaultValue::Reader::isNone() const { return which() == Declaration::Field::DefaultValue::NONE; } inline bool Declaration::Field::DefaultValue::Builder::isNone() { return which() == Declaration::Field::DefaultValue::NONE; } inline ::capnp::Void Declaration::Field::DefaultValue::Reader::getNone() const { KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::NONE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Field::DefaultValue::Builder::getNone() { KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::NONE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Field::DefaultValue::Builder::setNone( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::NONE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Field::DefaultValue::Reader::isValue() const { return which() == Declaration::Field::DefaultValue::VALUE; } inline bool Declaration::Field::DefaultValue::Builder::isValue() { return which() == Declaration::Field::DefaultValue::VALUE; } inline bool Declaration::Field::DefaultValue::Reader::hasValue() const { if (which() != Declaration::Field::DefaultValue::VALUE) return false; return !_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Field::DefaultValue::Builder::hasValue() { if (which() != Declaration::Field::DefaultValue::VALUE) return false; return !_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Field::DefaultValue::Reader::getValue() const { KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Field::DefaultValue::Builder::getValue() { KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline void Declaration::Field::DefaultValue::Builder::setValue( ::capnp::compiler::Expression::Reader value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Field::DefaultValue::Builder::initValue() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline void Declaration::Field::DefaultValue::Builder::adoptValue( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Field::DefaultValue::VALUE); ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Field::DefaultValue::Builder::disownValue() { KJ_IREQUIRE((which() == Declaration::Field::DefaultValue::VALUE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline bool Declaration::Interface::Reader::hasSuperclasses() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Interface::Builder::hasSuperclasses() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader Declaration::Interface::Reader::getSuperclasses() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Declaration::Interface::Builder::getSuperclasses() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Interface::Builder::setSuperclasses( ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>::Builder Declaration::Interface::Builder::initSuperclasses(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), size); } inline void Declaration::Interface::Builder::adoptSuperclasses( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>> Declaration::Interface::Builder::disownSuperclasses() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Expression, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Method::Reader::hasParams() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Method::Builder::hasParams() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Declaration::ParamList::Reader Declaration::Method::Reader::getParams() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Builder::getParams() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Declaration::ParamList::Pipeline Declaration::Method::Pipeline::getParams() { return ::capnp::compiler::Declaration::ParamList::Pipeline(_typeless.getPointerField(5)); } #endif // !CAPNP_LITE inline void Declaration::Method::Builder::setParams( ::capnp::compiler::Declaration::ParamList::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Builder::initParams() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Method::Builder::adoptParams( ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> Declaration::Method::Builder::disownParams() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline typename Declaration::Method::Results::Reader Declaration::Method::Reader::getResults() const { return typename Declaration::Method::Results::Reader(_reader); } inline typename Declaration::Method::Results::Builder Declaration::Method::Builder::getResults() { return typename Declaration::Method::Results::Builder(_builder); } #if !CAPNP_LITE inline typename Declaration::Method::Results::Pipeline Declaration::Method::Pipeline::getResults() { return typename Declaration::Method::Results::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Declaration::Method::Results::Builder Declaration::Method::Builder::initResults() { _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<6>() * ::capnp::POINTERS).clear(); return typename Declaration::Method::Results::Builder(_builder); } inline ::capnp::compiler::Declaration::Method::Results::Which Declaration::Method::Results::Reader::which() const { return _reader.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Declaration::Method::Results::Which Declaration::Method::Results::Builder::which() { return _builder.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline bool Declaration::Method::Results::Reader::isNone() const { return which() == Declaration::Method::Results::NONE; } inline bool Declaration::Method::Results::Builder::isNone() { return which() == Declaration::Method::Results::NONE; } inline ::capnp::Void Declaration::Method::Results::Reader::getNone() const { KJ_IREQUIRE((which() == Declaration::Method::Results::NONE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Declaration::Method::Results::Builder::getNone() { KJ_IREQUIRE((which() == Declaration::Method::Results::NONE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Declaration::Method::Results::Builder::setNone( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::NONE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Method::Results::Reader::isExplicit() const { return which() == Declaration::Method::Results::EXPLICIT; } inline bool Declaration::Method::Results::Builder::isExplicit() { return which() == Declaration::Method::Results::EXPLICIT; } inline bool Declaration::Method::Results::Reader::hasExplicit() const { if (which() != Declaration::Method::Results::EXPLICIT) return false; return !_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Method::Results::Builder::hasExplicit() { if (which() != Declaration::Method::Results::EXPLICIT) return false; return !_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Declaration::ParamList::Reader Declaration::Method::Results::Reader::getExplicit() const { KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_reader.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Results::Builder::getExplicit() { KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::get(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline void Declaration::Method::Results::Builder::setExplicit( ::capnp::compiler::Declaration::ParamList::Reader value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::set(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Declaration::ParamList::Builder Declaration::Method::Results::Builder::initExplicit() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::init(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline void Declaration::Method::Results::Builder::adoptExplicit( ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList>&& value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Declaration::Method::Results::EXPLICIT); ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::adopt(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Declaration::ParamList> Declaration::Method::Results::Builder::disownExplicit() { KJ_IREQUIRE((which() == Declaration::Method::Results::EXPLICIT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration::ParamList>::disown(_builder.getPointerField( ::capnp::bounded<6>() * ::capnp::POINTERS)); } inline bool Declaration::Annotation::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Declaration::Annotation::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Expression::Reader Declaration::Annotation::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Expression::Builder Declaration::Annotation::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Expression::Pipeline Declaration::Annotation::Pipeline::getType() { return ::capnp::compiler::Expression::Pipeline(_typeless.getPointerField(5)); } #endif // !CAPNP_LITE inline void Declaration::Annotation::Builder::setType( ::capnp::compiler::Expression::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Expression::Builder Declaration::Annotation::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Declaration::Annotation::Builder::adoptType( ::capnp::Orphan< ::capnp::compiler::Expression>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Expression> Declaration::Annotation::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Expression>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Declaration::Annotation::Reader::getTargetsFile() const { return _reader.getDataField( ::capnp::bounded<96>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsFile() { return _builder.getDataField( ::capnp::bounded<96>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsFile(bool value) { _builder.setDataField( ::capnp::bounded<96>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsConst() const { return _reader.getDataField( ::capnp::bounded<97>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsConst() { return _builder.getDataField( ::capnp::bounded<97>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsConst(bool value) { _builder.setDataField( ::capnp::bounded<97>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsEnum() const { return _reader.getDataField( ::capnp::bounded<98>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsEnum() { return _builder.getDataField( ::capnp::bounded<98>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsEnum(bool value) { _builder.setDataField( ::capnp::bounded<98>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsEnumerant() const { return _reader.getDataField( ::capnp::bounded<99>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsEnumerant() { return _builder.getDataField( ::capnp::bounded<99>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsEnumerant(bool value) { _builder.setDataField( ::capnp::bounded<99>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsStruct() const { return _reader.getDataField( ::capnp::bounded<100>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsStruct() { return _builder.getDataField( ::capnp::bounded<100>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsStruct(bool value) { _builder.setDataField( ::capnp::bounded<100>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsField() const { return _reader.getDataField( ::capnp::bounded<101>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsField() { return _builder.getDataField( ::capnp::bounded<101>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsField(bool value) { _builder.setDataField( ::capnp::bounded<101>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsUnion() const { return _reader.getDataField( ::capnp::bounded<102>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsUnion() { return _builder.getDataField( ::capnp::bounded<102>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsUnion(bool value) { _builder.setDataField( ::capnp::bounded<102>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsGroup() const { return _reader.getDataField( ::capnp::bounded<103>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsGroup() { return _builder.getDataField( ::capnp::bounded<103>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsGroup(bool value) { _builder.setDataField( ::capnp::bounded<103>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsInterface() const { return _reader.getDataField( ::capnp::bounded<104>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsInterface() { return _builder.getDataField( ::capnp::bounded<104>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsInterface(bool value) { _builder.setDataField( ::capnp::bounded<104>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsMethod() const { return _reader.getDataField( ::capnp::bounded<105>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsMethod() { return _builder.getDataField( ::capnp::bounded<105>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsMethod(bool value) { _builder.setDataField( ::capnp::bounded<105>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsParam() const { return _reader.getDataField( ::capnp::bounded<106>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsParam() { return _builder.getDataField( ::capnp::bounded<106>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsParam(bool value) { _builder.setDataField( ::capnp::bounded<106>() * ::capnp::ELEMENTS, value); } inline bool Declaration::Annotation::Reader::getTargetsAnnotation() const { return _reader.getDataField( ::capnp::bounded<107>() * ::capnp::ELEMENTS); } inline bool Declaration::Annotation::Builder::getTargetsAnnotation() { return _builder.getDataField( ::capnp::bounded<107>() * ::capnp::ELEMENTS); } inline void Declaration::Annotation::Builder::setTargetsAnnotation(bool value) { _builder.setDataField( ::capnp::bounded<107>() * ::capnp::ELEMENTS, value); } inline bool ParsedFile::Reader::hasRoot() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool ParsedFile::Builder::hasRoot() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::compiler::Declaration::Reader ParsedFile::Reader::getRoot() const { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Declaration::Builder ParsedFile::Builder::getRoot() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::compiler::Declaration::Pipeline ParsedFile::Pipeline::getRoot() { return ::capnp::compiler::Declaration::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void ParsedFile::Builder::setRoot( ::capnp::compiler::Declaration::Reader value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::compiler::Declaration::Builder ParsedFile::Builder::initRoot() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void ParsedFile::Builder::adoptRoot( ::capnp::Orphan< ::capnp::compiler::Declaration>&& value) { ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::compiler::Declaration> ParsedFile::Builder::disownRoot() { return ::capnp::_::PointerHelpers< ::capnp::compiler::Declaration>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/capnpc-c++.c++0000644000175000017500000037255014712011043022555 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This program is a code generator plugin for `capnp compile` which generates C++ code. #if _WIN32 #include #endif #include #include "../serialize.h" #include #include #include #include #include #include #include "../schema-loader.h" #include "../dynamic.h" #include #include #include #include #include #include #include #if _WIN32 #include #include #undef CONST #else #include #endif #if HAVE_CONFIG_H #include "config.h" #endif #ifndef VERSION #define VERSION "(unknown)" #endif namespace capnp { namespace { static constexpr uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull; static constexpr uint64_t NAME_ANNOTATION_ID = 0xf264a779fef191ceull; static constexpr uint64_t ALLOW_CANCELLATION_ANNOTATION_ID = 0xac7096ff8cfc9dceull; bool hasDiscriminantValue(const schema::Field::Reader& reader) { return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; } void enumerateDeps(schema::Type::Reader type, std::set& deps) { switch (type.which()) { case schema::Type::STRUCT: deps.insert(type.getStruct().getTypeId()); break; case schema::Type::ENUM: deps.insert(type.getEnum().getTypeId()); break; case schema::Type::INTERFACE: deps.insert(type.getInterface().getTypeId()); break; case schema::Type::LIST: enumerateDeps(type.getList().getElementType(), deps); break; default: break; } } void enumerateDeps(schema::Node::Reader node, std::set& deps) { switch (node.which()) { case schema::Node::STRUCT: { auto structNode = node.getStruct(); for (auto field: structNode.getFields()) { switch (field.which()) { case schema::Field::SLOT: enumerateDeps(field.getSlot().getType(), deps); break; case schema::Field::GROUP: deps.insert(field.getGroup().getTypeId()); break; } } if (structNode.getIsGroup()) { deps.insert(node.getScopeId()); } break; } case schema::Node::INTERFACE: { auto interfaceNode = node.getInterface(); for (auto superclass: interfaceNode.getSuperclasses()) { deps.insert(superclass.getId()); } for (auto method: interfaceNode.getMethods()) { deps.insert(method.getParamStructType()); deps.insert(method.getResultStructType()); } break; } default: break; } } struct OrderByName { template inline bool operator()(const T& a, const T& b) const { return a.getProto().getName() < b.getProto().getName(); } }; template kj::Array makeMembersByName(MemberList&& members) { auto sorted = KJ_MAP(member, members) { return member; }; std::sort(sorted.begin(), sorted.end(), OrderByName()); return KJ_MAP(member, sorted) { return member.getIndex(); }; } kj::StringPtr baseName(kj::StringPtr path) { KJ_IF_MAYBE(slashPos, path.findLast('/')) { return path.slice(*slashPos + 1); } else { return path; } } kj::String safeIdentifier(kj::StringPtr identifier) { // Given a desired identifier name, munge it to make it safe for use in generated code. // // If the identifier is a keyword, this adds an underscore to the end. static const std::set keywords({ "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", "compl", "const", "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", "switch", "template", "this", "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq" }); if (keywords.count(identifier) > 0) { return kj::str(identifier, '_'); } else { return kj::heapString(identifier); } } // ======================================================================================= class CppTypeName { // Used to build a C++ type name string. This is complicated in the presence of templates, // because we must add the "typename" and "template" disambiguator keywords as needed. public: inline CppTypeName(): isArgDependent(false), needsTypename(false), hasInterfaces_(false), hasDisambiguatedTemplate_(false) {} CppTypeName(CppTypeName&& other) = default; CppTypeName(const CppTypeName& other) : name(kj::strTree(other.name.flatten())), isArgDependent(other.isArgDependent), needsTypename(other.needsTypename), hasInterfaces_(other.hasInterfaces_), hasDisambiguatedTemplate_(other.hasDisambiguatedTemplate_) {} CppTypeName& operator=(CppTypeName&& other) = default; CppTypeName& operator=(const CppTypeName& other) { name = kj::strTree(other.name.flatten()); isArgDependent = other.isArgDependent; needsTypename = other.needsTypename; return *this; } static CppTypeName makeRoot() { return CppTypeName(kj::strTree(" "), false); } static CppTypeName makeNamespace(kj::StringPtr name) { return CppTypeName(kj::strTree(" ::", name), false); } static CppTypeName makeTemplateParam(kj::StringPtr name) { return CppTypeName(kj::strTree(name), true); } static CppTypeName makePrimitive(kj::StringPtr name) { return CppTypeName(kj::strTree(name), false); } void addMemberType(kj::StringPtr innerName) { // Append "::innerName" to refer to a member. name = kj::strTree(kj::mv(name), "::", innerName); needsTypename = isArgDependent; } void addMemberValue(kj::StringPtr innerName) { // Append "::innerName" to refer to a member. name = kj::strTree(kj::mv(name), "::", innerName); needsTypename = false; } bool hasDisambiguatedTemplate() { return hasDisambiguatedTemplate_; } void addMemberTemplate(kj::StringPtr innerName, kj::Array&& params) { // Append "::innerName". // // If necessary, add the "template" disambiguation keyword in front of `innerName`. bool parentIsArgDependent = isArgDependent; needsTypename = parentIsArgDependent; hasDisambiguatedTemplate_ = hasDisambiguatedTemplate_ || parentIsArgDependent; name = kj::strTree(kj::mv(name), parentIsArgDependent ? "::template " : "::", innerName, '<', kj::StringTree(KJ_MAP(p, params) { if (p.isArgDependent) isArgDependent = true; if (p.hasInterfaces_) hasInterfaces_ = true; if (p.hasDisambiguatedTemplate_) hasDisambiguatedTemplate_ = true; return kj::strTree(kj::mv(p)); }, ", "), '>'); } void setHasInterfaces() { hasInterfaces_ = true; } bool hasInterfaces() { return hasInterfaces_; } kj::StringTree strNoTypename() const & { return name.flatten(); } kj::StringTree strNoTypename() && { return kj::mv(name); } // Stringify but never prefix with `typename`. Use in contexts where `typename` is implicit. private: kj::StringTree name; bool isArgDependent; // Does the name contain any template-argument-dependent types? bool needsTypename; // Does the name require a prefix of "typename"? bool hasInterfaces_; // Does this type name refer to any interface types? If so it may need to be #ifdefed out in // lite mode. bool hasDisambiguatedTemplate_; // Whether the type name contains a template type that had to be disambiguated using the // "template" keyword, e.g. "Foo::template Bar". // // TODO(msvc): We only track this because MSVC seems to get confused by it in some weird cases. inline CppTypeName(kj::StringTree&& name, bool isArgDependent) : name(kj::mv(name)), isArgDependent(isArgDependent), needsTypename(false), hasInterfaces_(false), hasDisambiguatedTemplate_(false) {} friend kj::StringTree KJ_STRINGIFY(CppTypeName&& typeName); friend kj::String KJ_STRINGIFY(const CppTypeName& typeName); }; kj::StringTree KJ_STRINGIFY(CppTypeName&& typeName) { if (typeName.needsTypename) { return kj::strTree("typename ", kj::mv(typeName.name)); } else { return kj::mv(typeName.name); } } kj::String KJ_STRINGIFY(const CppTypeName& typeName) { if (typeName.needsTypename) { return kj::str("typename ", typeName.name); } else { return typeName.name.flatten(); } } CppTypeName whichKind(Type type) { // Make a CppTypeName representing the capnp::Kind value for the given schema type. This makes // CppTypeName conflate types and values, but this is all just a hack for MSVC's benefit. Its // primary use is as a non-type template parameter to `capnp::List` -- normally the Kind K // is deduced via SFINAE, but MSVC just can't do it in certain cases, such as when a nested type // of `capnp::List` is the return type of a function, and the element type T is a template // instantiation. switch (type.which()) { case schema::Type::VOID: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::BOOL: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::INT8: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::INT16: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::INT32: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::INT64: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::UINT8: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::UINT16: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::UINT32: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::UINT64: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::FLOAT32: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::FLOAT64: return CppTypeName::makePrimitive(" ::capnp::Kind::PRIMITIVE"); case schema::Type::TEXT: return CppTypeName::makePrimitive(" ::capnp::Kind::BLOB"); case schema::Type::DATA: return CppTypeName::makePrimitive(" ::capnp::Kind::BLOB"); case schema::Type::ENUM: return CppTypeName::makePrimitive(" ::capnp::Kind::ENUM"); case schema::Type::STRUCT: return CppTypeName::makePrimitive(" ::capnp::Kind::STRUCT"); case schema::Type::INTERFACE: return CppTypeName::makePrimitive(" ::capnp::Kind::INTERFACE"); case schema::Type::LIST: return CppTypeName::makePrimitive(" ::capnp::Kind::LIST"); case schema::Type::ANY_POINTER: { switch (type.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::CAPABILITY: return CppTypeName::makePrimitive(" ::capnp::Kind::INTERFACE"); default: return CppTypeName::makePrimitive(" ::capnp::Kind::OTHER"); } } } KJ_UNREACHABLE; } // ======================================================================================= class CapnpcCppMain { public: CapnpcCppMain(kj::ProcessContext& context): context(context) {} kj::MainFunc getMain() { return kj::MainBuilder(context, "Cap'n Proto C++ plugin version " VERSION, "This is a Cap'n Proto compiler plugin which generates C++ code. " "It is meant to be run using the Cap'n Proto compiler, e.g.:\n" " capnp compile -oc++ foo.capnp") .callAfterParsing(KJ_BIND_METHOD(*this, run)) .build(); } private: kj::ProcessContext& context; SchemaLoader schemaLoader; std::unordered_set usedImports; bool hasInterfaces = false; CppTypeName cppFullName(Schema schema, kj::Maybe method) { return cppFullName(schema, schema, method); } CppTypeName cppFullName(Schema schema, Schema brand, kj::Maybe method) { auto node = schema.getProto(); if (node.getScopeId() == 0) { // This is the file-level scope. Search for the namespace annotation. KJ_REQUIRE(node.isFile(), "Non-file had scopeId zero; perhaps it's a method param / result struct?"); usedImports.insert(node.getId()); KJ_IF_MAYBE(ns, annotationValue(node, NAMESPACE_ANNOTATION_ID)) { return CppTypeName::makeNamespace(ns->getText()); } else { return CppTypeName::makeRoot(); } } else { // This is a named type. // Figure out what name to use. Schema parent = schemaLoader.get(node.getScopeId()); kj::StringPtr unqualifiedName; kj::String ownUnqualifiedName; KJ_IF_MAYBE(annotatedName, annotationValue(node, NAME_ANNOTATION_ID)) { // The node's name has been overridden for C++ by an annotation. unqualifiedName = annotatedName->getText(); } else { // Search among the parent's nested nodes to for this node, in order to determine its name. auto parentProto = parent.getProto(); for (auto nested: parentProto.getNestedNodes()) { if (nested.getId() == node.getId()) { unqualifiedName = nested.getName(); break; } } if (unqualifiedName == nullptr) { // Hmm, maybe it's a group node? if (parentProto.isStruct()) { for (auto field: parentProto.getStruct().getFields()) { if (field.isGroup() && field.getGroup().getTypeId() == node.getId()) { ownUnqualifiedName = toTitleCase(protoName(field)); unqualifiedName = ownUnqualifiedName; break; } } } } KJ_REQUIRE(unqualifiedName != nullptr, "A schema Node's supposed scope did not contain the node as a NestedNode."); } auto result = cppFullName(parent, brand, method); // Construct the generic arguments. auto params = node.getParameters(); if (params.size() > 0) { auto args = brand.getBrandArgumentsAtScope(node.getId()); #if 0 // Figure out exactly how many params are not bound to AnyPointer. // TODO(msvc): In a few obscure cases, MSVC does not like empty template parameter lists, // even if all parameters have defaults. So, we give in and explicitly list all // parameters in our generated code for now. Try again later. uint paramCount = 0; for (uint i: kj::indices(params)) { auto arg = args[i]; if (arg.which() != schema::Type::ANY_POINTER || arg.getBrandParameter() != nullptr || (arg.getImplicitParameter() != nullptr && method != nullptr)) { paramCount = i + 1; } } #else uint paramCount = params.size(); #endif result.addMemberTemplate(unqualifiedName, KJ_MAP(i, kj::range(0u, paramCount)) { return typeName(args[i], method); }); } else { result.addMemberType(unqualifiedName); } return result; } } kj::String toUpperCase(kj::StringPtr name) { kj::Vector result(name.size() + 4); for (char c: name) { if ('a' <= c && c <= 'z') { result.add(c - 'a' + 'A'); } else if (result.size() > 0 && 'A' <= c && c <= 'Z') { result.add('_'); result.add(c); } else { result.add(c); } } if (result.size() == 4 && memcmp(result.begin(), "NULL", 4) == 0) { // NULL probably collides with a macro. result.add('_'); } result.add('\0'); return kj::String(result.releaseAsArray()); } kj::String toTitleCase(kj::StringPtr name) { kj::String result = kj::heapString(name); if ('a' <= result[0] && result[0] <= 'z') { result[0] = result[0] - 'a' + 'A'; } return kj::mv(result); } CppTypeName typeName(Type type, kj::Maybe method) { switch (type.which()) { case schema::Type::VOID: return CppTypeName::makePrimitive(" ::capnp::Void"); case schema::Type::BOOL: return CppTypeName::makePrimitive("bool"); case schema::Type::INT8: return CppTypeName::makePrimitive(" ::int8_t"); case schema::Type::INT16: return CppTypeName::makePrimitive(" ::int16_t"); case schema::Type::INT32: return CppTypeName::makePrimitive(" ::int32_t"); case schema::Type::INT64: return CppTypeName::makePrimitive(" ::int64_t"); case schema::Type::UINT8: return CppTypeName::makePrimitive(" ::uint8_t"); case schema::Type::UINT16: return CppTypeName::makePrimitive(" ::uint16_t"); case schema::Type::UINT32: return CppTypeName::makePrimitive(" ::uint32_t"); case schema::Type::UINT64: return CppTypeName::makePrimitive(" ::uint64_t"); case schema::Type::FLOAT32: return CppTypeName::makePrimitive("float"); case schema::Type::FLOAT64: return CppTypeName::makePrimitive("double"); case schema::Type::TEXT: return CppTypeName::makePrimitive(" ::capnp::Text"); case schema::Type::DATA: return CppTypeName::makePrimitive(" ::capnp::Data"); case schema::Type::ENUM: return cppFullName(type.asEnum(), method); case schema::Type::STRUCT: return cppFullName(type.asStruct(), method); case schema::Type::INTERFACE: { auto result = cppFullName(type.asInterface(), method); result.setHasInterfaces(); return result; } case schema::Type::LIST: { CppTypeName result = CppTypeName::makeNamespace("capnp"); auto params = kj::heapArrayBuilder(2); auto list = type.asList(); params.add(typeName(list.getElementType(), method)); params.add(whichKind(list.getElementType())); result.addMemberTemplate("List", params.finish()); return result; } case schema::Type::ANY_POINTER: KJ_IF_MAYBE(param, type.getBrandParameter()) { return CppTypeName::makeTemplateParam(schemaLoader.get(param->scopeId).getProto() .getParameters()[param->index].getName()); } else KJ_IF_MAYBE(param, type.getImplicitParameter()) { KJ_IF_MAYBE(m, method) { auto params = m->getProto().getImplicitParameters(); KJ_REQUIRE(param->index < params.size()); return CppTypeName::makeTemplateParam(params[param->index].getName()); } else { return CppTypeName::makePrimitive(" ::capnp::AnyPointer"); } } else { switch (type.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::ANY_KIND: return CppTypeName::makePrimitive(" ::capnp::AnyPointer"); case schema::Type::AnyPointer::Unconstrained::STRUCT: return CppTypeName::makePrimitive(" ::capnp::AnyStruct"); case schema::Type::AnyPointer::Unconstrained::LIST: return CppTypeName::makePrimitive(" ::capnp::AnyList"); case schema::Type::AnyPointer::Unconstrained::CAPABILITY: { hasInterfaces = true; // Probably need to #include . auto result = CppTypeName::makePrimitive(" ::capnp::Capability"); result.setHasInterfaces(); return result; } } KJ_UNREACHABLE; } } KJ_UNREACHABLE; } template kj::Maybe annotationValue(P proto, uint64_t annotationId) { for (auto annotation: proto.getAnnotations()) { if (annotation.getId() == annotationId) { return annotation.getValue(); } } return nullptr; } template kj::StringPtr protoName(P proto) { KJ_IF_MAYBE(name, annotationValue(proto, NAME_ANNOTATION_ID)) { return name->getText(); } else { return proto.getName(); } } kj::StringTree literalValue(Type type, schema::Value::Reader value) { switch (value.which()) { case schema::Value::VOID: return kj::strTree(" ::capnp::VOID"); case schema::Value::BOOL: return kj::strTree(value.getBool() ? "true" : "false"); case schema::Value::INT8: return kj::strTree(value.getInt8()); case schema::Value::INT16: return kj::strTree(value.getInt16()); case schema::Value::INT32: return kj::strTree(value.getInt32()); case schema::Value::INT64: return kj::strTree(value.getInt64(), "ll"); case schema::Value::UINT8: return kj::strTree(value.getUint8(), "u"); case schema::Value::UINT16: return kj::strTree(value.getUint16(), "u"); case schema::Value::UINT32: return kj::strTree(value.getUint32(), "u"); case schema::Value::UINT64: return kj::strTree(value.getUint64(), "llu"); case schema::Value::FLOAT32: { auto text = kj::str(value.getFloat32()); if (text.findFirst('.') == nullptr && text.findFirst('e') == nullptr && text.findFirst('E') == nullptr) { text = kj::str(text, ".0"); } return kj::strTree(kj::mv(text), "f"); } case schema::Value::FLOAT64: return kj::strTree(value.getFloat64()); case schema::Value::ENUM: { EnumSchema schema = type.asEnum(); if (value.getEnum() < schema.getEnumerants().size()) { return kj::strTree( cppFullName(schema, nullptr), "::", toUpperCase(protoName(schema.getEnumerants()[value.getEnum()].getProto()))); } else { return kj::strTree("static_cast<", cppFullName(schema, nullptr), ">(", value.getEnum(), ")"); } } case schema::Value::TEXT: case schema::Value::DATA: case schema::Value::STRUCT: case schema::Value::INTERFACE: case schema::Value::LIST: case schema::Value::ANY_POINTER: KJ_FAIL_REQUIRE("literalValue() can only be used on primitive types."); } KJ_UNREACHABLE; } // ----------------------------------------------------------------- class TemplateContext { public: TemplateContext(): parent(nullptr) {} explicit TemplateContext(schema::Node::Reader node) : parent(nullptr), node(node) {} TemplateContext(const TemplateContext& parent, kj::StringPtr name, schema::Node::Reader node) : parent(parent), name(name), node(node) {} bool hasParams() const { return node.getParameters().size() > 0; } bool isGeneric() const { return node.getIsGeneric(); } kj::Maybe getParent() const { return parent; } kj::StringPtr getName() const { return name; } kj::StringTree decl(bool withDefaults, kj::StringPtr suffix = nullptr) const { // "template " for this type. Includes default assignments // ("= ::capnp::AnyPointer") if `withDefaults` is true. Returns empty string if this type // is not parameterized. auto params = node.getParameters(); if (params.size() == 0) { return kj::strTree(); } else { return kj::strTree( "template <", kj::StringTree(KJ_MAP(p, params) { return kj::strTree("typename ", p.getName(), suffix, withDefaults ? " = ::capnp::AnyPointer" : ""); }, ", "), ">\n"); } } kj::StringTree allDecls() const { // Decl for each generic parent plus this type, one per line. return kj::strTree(parentDecls(), decl(false)); } kj::StringTree parentDecls() const { // Decls just for the parents. KJ_IF_MAYBE(p, parent) { return p->allDecls(); } else { return kj::strTree(); } } kj::StringTree args(kj::StringPtr suffix = nullptr) const { // "" for this type. auto params = node.getParameters(); if (params.size() == 0) { return kj::strTree(); } else { return kj::strTree( "<", kj::StringTree(KJ_MAP(p, params) { return kj::strTree(p.getName(), suffix); }, ", "), ">"); } } kj::StringTree allArgs() const { // "S, T, U, V" -- listing all args for all enclosing scopes starting from the outermost. auto params = node.getParameters(); kj::StringTree self(KJ_MAP(p, params) { return kj::strTree(p.getName()); }, ", "); kj::StringTree up; KJ_IF_MAYBE(p, parent) { up = p->allArgs(); } if (self.size() == 0) { return up; } else if (up.size() == 0) { return self; } else { return kj::strTree(kj::mv(up), ", ", kj::mv(self)); } } std::map::Reader> getScopeMap() const { std::map::Reader> result; const TemplateContext* current = this; for (;;) { auto params = current->node.getParameters(); if (params.size() > 0) { result[current->node.getId()] = params; } KJ_IF_MAYBE(p, current->parent) { current = p; } else { return result; } } } private: kj::Maybe parent; kj::StringPtr name; schema::Node::Reader node; }; struct BrandInitializerText { kj::StringTree scopes; kj::StringTree bindings; kj::StringTree dependencies; size_t dependencyCount; // TODO(msvc): `dependencyCount` is the number of individual dependency definitions in // `dependencies`. It's a hack to allow makeGenericDefinitions to hard-code the size of the // `_capnpPrivate::brandDependencies` array into the definition of // `_capnpPrivate::specificBrand::dependencyCount`. This is necessary because MSVC cannot // deduce the size of `brandDependencies` if it is nested under a class template. It's // probably this demoralizingly deferred bug: // https://connect.microsoft.com/VisualStudio/feedback/details/759407/can-not-get-size-of-static-array-defined-in-class-template }; BrandInitializerText makeBrandInitializers( const TemplateContext& templateContext, Schema schema) { auto scopeMap = templateContext.getScopeMap(); auto scopes = kj::heapArrayBuilder(scopeMap.size()); kj::Vector bindings(scopeMap.size() * 2); // (estimate two params per scope) for (auto& scope: scopeMap) { scopes.add(kj::strTree(" { ", "0x", kj::hex(scope.first), ", " "brandBindings + ", bindings.size(), ", ", scope.second.size(), ", " "false" "},\n")); for (auto param: scope.second) { bindings.add(kj::strTree(" ::capnp::_::brandBindingFor<", param.getName(), ">(),\n")); } } auto depMap = makeBrandDepMap(templateContext, schema); auto dependencyCount = depMap.size(); return { kj::strTree("{\n", scopes.finish(), "}"), kj::strTree("{\n", bindings.releaseAsArray(), "}"), makeBrandDepInitializers(kj::mv(depMap)), dependencyCount }; } std::map makeBrandDepMap(const TemplateContext& templateContext, Schema schema) { // Build deps. This is separate from makeBrandDepInitializers to give calling code the // opportunity to count the number of dependencies, to calculate array sizes. std::map depMap; #define ADD_DEP(kind, index, ...) \ { \ uint location = _::RawBrandedSchema::makeDepLocation( \ _::RawBrandedSchema::DepKind::kind, index); \ KJ_IF_MAYBE(dep, makeBrandDepInitializer(__VA_ARGS__)) { \ depMap[location] = kj::mv(*dep); \ } \ } switch (schema.getProto().which()) { case schema::Node::FILE: case schema::Node::ENUM: case schema::Node::ANNOTATION: break; case schema::Node::STRUCT: for (auto field: schema.asStruct().getFields()) { ADD_DEP(FIELD, field.getIndex(), field.getType()); } break; case schema::Node::INTERFACE: { auto interface = schema.asInterface(); auto superclasses = interface.getSuperclasses(); for (auto i: kj::indices(superclasses)) { ADD_DEP(SUPERCLASS, i, superclasses[i]); } auto methods = interface.getMethods(); for (auto i: kj::indices(methods)) { auto method = methods[i]; ADD_DEP(METHOD_PARAMS, i, method, method.getParamType(), "Params"); ADD_DEP(METHOD_RESULTS, i, method, method.getResultType(), "Results"); } break; } case schema::Node::CONST: ADD_DEP(CONST_TYPE, 0, schema.asConst().getType()); break; } #undef ADD_DEP return depMap; } kj::StringTree makeBrandDepInitializers(std::map&& depMap) { // Process depMap. Returns a braced initialiser list, or an empty string if there are no // dependencies. if (!depMap.size()) { return kj::strTree(); } auto deps = kj::heapArrayBuilder(depMap.size()); for (auto& entry: depMap) { deps.add(kj::strTree(" { ", entry.first, ", ", kj::mv(entry.second), " },\n")); } return kj::strTree("{\n", kj::StringTree(deps.finish(), ""), "}"); } kj::Maybe makeBrandDepInitializer(Schema type) { // Be careful not to invoke cppFullName() if it would just be thrown away, as doing so will // add the type's declaring file to `usedImports`. In particular, this causes `stream.capnp.h` // to be #included unnecessarily. if (type.isBranded()) { return makeBrandDepInitializer(type, cppFullName(type, nullptr)); } else { return nullptr; } } kj::Maybe makeBrandDepInitializer( InterfaceSchema::Method method, StructSchema type, kj::StringPtr suffix) { auto typeProto = type.getProto(); if (typeProto.getScopeId() == 0) { // This is an auto-generated params or results type. auto name = cppFullName(method.getContainingInterface(), nullptr); auto memberTypeName = kj::str(toTitleCase(protoName(method.getProto())), suffix); if (typeProto.getParameters().size() == 0) { name.addMemberType(memberTypeName); } else { // The method has implicit parameters (i.e. it's generic). For the purpose of the brand // dep initializer, we only want to supply the default AnyPointer variant, so just don't // pass any parameters here. name.addMemberTemplate(memberTypeName, nullptr); } return makeBrandDepInitializer(type, kj::mv(name)); } else { return makeBrandDepInitializer(type); } } kj::Maybe makeBrandDepInitializer(Schema type, CppTypeName name) { if (type.isBranded()) { name.addMemberType("_capnpPrivate"); name.addMemberValue("brand"); return kj::strTree(name, "()"); } else { return nullptr; } } kj::Maybe makeBrandDepInitializer(Type type) { switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ENUM: case schema::Type::ANY_POINTER: return nullptr; case schema::Type::STRUCT: return makeBrandDepInitializer(type.asStruct()); case schema::Type::INTERFACE: return makeBrandDepInitializer(type.asInterface()); case schema::Type::LIST: return makeBrandDepInitializer(type.asList().getElementType()); } KJ_UNREACHABLE; } // ----------------------------------------------------------------- // Code to deal with "slots" -- determines what to zero out when we clear a group. static uint typeSizeBits(schema::Type::Which whichType) { switch (whichType) { case schema::Type::BOOL: return 1; case schema::Type::INT8: return 8; case schema::Type::INT16: return 16; case schema::Type::INT32: return 32; case schema::Type::INT64: return 64; case schema::Type::UINT8: return 8; case schema::Type::UINT16: return 16; case schema::Type::UINT32: return 32; case schema::Type::UINT64: return 64; case schema::Type::FLOAT32: return 32; case schema::Type::FLOAT64: return 64; case schema::Type::ENUM: return 16; case schema::Type::VOID: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("Should only be called for data types."); } KJ_UNREACHABLE; } enum class Section { NONE, DATA, POINTERS }; static Section sectionFor(schema::Type::Which whichType) { switch (whichType) { case schema::Type::VOID: return Section::NONE; case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: return Section::DATA; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: return Section::POINTERS; } KJ_UNREACHABLE; } static kj::StringPtr maskType(schema::Type::Which whichType) { switch (whichType) { case schema::Type::BOOL: return "bool"; case schema::Type::INT8: return " ::uint8_t"; case schema::Type::INT16: return " ::uint16_t"; case schema::Type::INT32: return " ::uint32_t"; case schema::Type::INT64: return " ::uint64_t"; case schema::Type::UINT8: return " ::uint8_t"; case schema::Type::UINT16: return " ::uint16_t"; case schema::Type::UINT32: return " ::uint32_t"; case schema::Type::UINT64: return " ::uint64_t"; case schema::Type::FLOAT32: return " ::uint32_t"; case schema::Type::FLOAT64: return " ::uint64_t"; case schema::Type::ENUM: return " ::uint16_t"; case schema::Type::VOID: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("Should only be called for data types."); } KJ_UNREACHABLE; } struct Slot { schema::Type::Which whichType; uint offset; bool isSupersetOf(Slot other) const { auto section = sectionFor(whichType); if (section != sectionFor(other.whichType)) return false; switch (section) { case Section::NONE: return true; // all voids overlap case Section::DATA: { auto bits = typeSizeBits(whichType); auto start = offset * bits; auto otherBits = typeSizeBits(other.whichType); auto otherStart = other.offset * otherBits; return start <= otherStart && otherStart + otherBits <= start + bits; } case Section::POINTERS: return offset == other.offset; } KJ_UNREACHABLE; } bool operator<(Slot other) const { // Sort by section, then start position, and finally size. auto section = sectionFor(whichType); auto otherSection = sectionFor(other.whichType); if (section < otherSection) { return true; } else if (section > otherSection) { return false; } switch (section) { case Section::NONE: return false; case Section::DATA: { auto bits = typeSizeBits(whichType); auto start = offset * bits; auto otherBits = typeSizeBits(other.whichType); auto otherStart = other.offset * otherBits; if (start < otherStart) { return true; } else if (start > otherStart) { return false; } // Sort larger sizes before smaller. return bits > otherBits; } case Section::POINTERS: return offset < other.offset; } KJ_UNREACHABLE; } }; void getSlots(StructSchema schema, kj::Vector& slots) { auto structProto = schema.getProto().getStruct(); if (structProto.getDiscriminantCount() > 0) { slots.add(Slot { schema::Type::UINT16, structProto.getDiscriminantOffset() }); } for (auto field: schema.getFields()) { auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); slots.add(Slot { slot.getType().which(), slot.getOffset() }); break; } case schema::Field::GROUP: getSlots(field.getType().asStruct(), slots); break; } } } kj::Array getSortedSlots(StructSchema schema) { // Get a representation of all of the field locations owned by this schema, e.g. so that they // can be zero'd out. kj::Vector slots(schema.getFields().size()); getSlots(schema, slots); std::sort(slots.begin(), slots.end()); kj::Vector result(slots.size()); // All void slots are redundant, and they sort towards the front of the list. By starting out // with `prevSlot` = void, we will end up skipping them all, which is what we want. Slot prevSlot = { schema::Type::VOID, 0 }; for (auto slot: slots) { if (prevSlot.isSupersetOf(slot)) { // This slot is redundant as prevSlot is a superset of it. continue; } // Since all sizes are power-of-two, if two slots overlap at all, one must be a superset of // the other. Since we sort slots by starting position, we know that the only way `slot` // could be a superset of `prevSlot` is if they have the same starting position. However, // since we sort slots with the same starting position by descending size, this is not // possible. KJ_DASSERT(!slot.isSupersetOf(prevSlot)); result.add(slot); prevSlot = slot; } return result.releaseAsArray(); } // ----------------------------------------------------------------- struct DiscriminantChecks { kj::String has; kj::String check; kj::String set; kj::StringTree readerIsDecl; kj::StringTree builderIsDecl; kj::StringTree isDefs; }; DiscriminantChecks makeDiscriminantChecks(kj::StringPtr scope, kj::StringPtr memberName, StructSchema containingStruct, const TemplateContext& templateContext) { auto discrimOffset = containingStruct.getProto().getStruct().getDiscriminantOffset(); kj::String titleCase = toTitleCase(memberName); kj::String upperCase = toUpperCase(memberName); return DiscriminantChecks { kj::str( " if (which() != ", scope, upperCase, ") return false;\n"), kj::str( // Extra parens around the condition are needed for when we're compiling a multi-arg // generic type, which will have a comma, which would otherwise mess up the macro. // Ah, C++. " KJ_IREQUIRE((which() == ", scope, upperCase, "),\n" " \"Must check which() before get()ing a union member.\");\n"), kj::str( " _builder.setDataField<", scope, "Which>(\n" " ::capnp::bounded<", discrimOffset, ">() * ::capnp::ELEMENTS, ", scope, upperCase, ");\n"), kj::strTree(" inline bool is", titleCase, "() const;\n"), kj::strTree(" inline bool is", titleCase, "();\n"), kj::strTree( templateContext.allDecls(), "inline bool ", scope, "Reader::is", titleCase, "() const {\n" " return which() == ", scope, upperCase, ";\n" "}\n", templateContext.allDecls(), "inline bool ", scope, "Builder::is", titleCase, "() {\n" " return which() == ", scope, upperCase, ";\n" "}\n") }; } // ----------------------------------------------------------------- struct FieldText { kj::StringTree readerMethodDecls; kj::StringTree builderMethodDecls; kj::StringTree pipelineMethodDecls; kj::StringTree inlineMethodDefs; }; enum class FieldKind { PRIMITIVE, BLOB, STRUCT, LIST, INTERFACE, ANY_POINTER, BRAND_PARAMETER }; FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field field, const TemplateContext& templateContext) { auto proto = field.getProto(); auto typeSchema = field.getType(); auto baseName = protoName(proto); kj::String titleCase = toTitleCase(baseName); DiscriminantChecks unionDiscrim; if (hasDiscriminantValue(proto)) { unionDiscrim = makeDiscriminantChecks(scope, baseName, field.getContainingStruct(), templateContext); } switch (proto.which()) { case schema::Field::SLOT: // Continue below. break; case schema::Field::GROUP: { auto slots = getSortedSlots(field.getType().asStruct()); return FieldText { kj::strTree( kj::mv(unionDiscrim.readerIsDecl), " inline typename ", titleCase, "::Reader get", titleCase, "() const;\n" "\n"), kj::strTree( kj::mv(unionDiscrim.builderIsDecl), " inline typename ", titleCase, "::Builder get", titleCase, "();\n" " inline typename ", titleCase, "::Builder init", titleCase, "();\n" "\n"), hasDiscriminantValue(proto) ? kj::strTree() : kj::strTree(" inline typename ", titleCase, "::Pipeline get", titleCase, "();\n"), kj::strTree( kj::mv(unionDiscrim.isDefs), templateContext.allDecls(), "inline typename ", scope, titleCase, "::Reader ", scope, "Reader::get", titleCase, "() const {\n", unionDiscrim.check, " return typename ", scope, titleCase, "::Reader(_reader);\n" "}\n", templateContext.allDecls(), "inline typename ", scope, titleCase, "::Builder ", scope, "Builder::get", titleCase, "() {\n", unionDiscrim.check, " return typename ", scope, titleCase, "::Builder(_builder);\n" "}\n", hasDiscriminantValue(proto) ? kj::strTree() : kj::strTree( "#if !CAPNP_LITE\n", templateContext.allDecls(), "inline typename ", scope, titleCase, "::Pipeline ", scope, "Pipeline::get", titleCase, "() {\n", " return typename ", scope, titleCase, "::Pipeline(_typeless.noop());\n" "}\n" "#endif // !CAPNP_LITE\n"), templateContext.allDecls(), "inline typename ", scope, titleCase, "::Builder ", scope, "Builder::init", titleCase, "() {\n", unionDiscrim.set, KJ_MAP(slot, slots) { switch (sectionFor(slot.whichType)) { case Section::NONE: return kj::strTree(); case Section::DATA: return kj::strTree( " _builder.setDataField<", maskType(slot.whichType), ">(::capnp::bounded<", slot.offset, ">() * ::capnp::ELEMENTS, 0);\n"); case Section::POINTERS: return kj::strTree( " _builder.getPointerField(::capnp::bounded<", slot.offset, ">() * ::capnp::POINTERS).clear();\n"); } KJ_UNREACHABLE; }, " return typename ", scope, titleCase, "::Builder(_builder);\n" "}\n") }; } } auto slot = proto.getSlot(); FieldKind kind = FieldKind::PRIMITIVE; kj::String ownedType; CppTypeName type = typeName(typeSchema, nullptr); kj::StringPtr setterDefault; // only for void kj::String defaultMask; // primitives only size_t defaultOffset = 0; // pointers only: offset of the default value within the schema. size_t defaultSize = 0; // blobs only: byte size of the default value. auto defaultBody = slot.getDefaultValue(); switch (typeSchema.which()) { case schema::Type::VOID: kind = FieldKind::PRIMITIVE; setterDefault = " = ::capnp::VOID"; break; #define HANDLE_PRIMITIVE(discrim, typeName, defaultName, suffix) \ case schema::Type::discrim: \ kind = FieldKind::PRIMITIVE; \ if (defaultBody.get##defaultName() != 0) { \ defaultMask = kj::str(defaultBody.get##defaultName(), #suffix); \ } \ break; HANDLE_PRIMITIVE(BOOL, bool, Bool, ); HANDLE_PRIMITIVE(INT8 , ::int8_t , Int8 , ); HANDLE_PRIMITIVE(INT16, ::int16_t, Int16, ); HANDLE_PRIMITIVE(INT32, ::int32_t, Int32, ); HANDLE_PRIMITIVE(INT64, ::int64_t, Int64, ll); HANDLE_PRIMITIVE(UINT8 , ::uint8_t , Uint8 , u); HANDLE_PRIMITIVE(UINT16, ::uint16_t, Uint16, u); HANDLE_PRIMITIVE(UINT32, ::uint32_t, Uint32, u); HANDLE_PRIMITIVE(UINT64, ::uint64_t, Uint64, ull); #undef HANDLE_PRIMITIVE case schema::Type::FLOAT32: kind = FieldKind::PRIMITIVE; if (defaultBody.getFloat32() != 0) { uint32_t mask; float value = defaultBody.getFloat32(); static_assert(sizeof(mask) == sizeof(value), "bug"); memcpy(&mask, &value, sizeof(mask)); defaultMask = kj::str(mask, "u"); } break; case schema::Type::FLOAT64: kind = FieldKind::PRIMITIVE; if (defaultBody.getFloat64() != 0) { uint64_t mask; double value = defaultBody.getFloat64(); static_assert(sizeof(mask) == sizeof(value), "bug"); memcpy(&mask, &value, sizeof(mask)); defaultMask = kj::str(mask, "ull"); } break; case schema::Type::TEXT: kind = FieldKind::BLOB; if (defaultBody.hasText()) { defaultOffset = field.getDefaultValueSchemaOffset(); defaultSize = defaultBody.getText().size(); } break; case schema::Type::DATA: kind = FieldKind::BLOB; if (defaultBody.hasData()) { defaultOffset = field.getDefaultValueSchemaOffset(); defaultSize = defaultBody.getData().size(); } break; case schema::Type::ENUM: kind = FieldKind::PRIMITIVE; if (defaultBody.getEnum() != 0) { defaultMask = kj::str(defaultBody.getEnum(), "u"); } break; case schema::Type::STRUCT: kind = FieldKind::STRUCT; if (defaultBody.hasStruct()) { defaultOffset = field.getDefaultValueSchemaOffset(); } break; case schema::Type::LIST: kind = FieldKind::LIST; if (defaultBody.hasList()) { defaultOffset = field.getDefaultValueSchemaOffset(); } break; case schema::Type::INTERFACE: kind = FieldKind::INTERFACE; break; case schema::Type::ANY_POINTER: if (defaultBody.hasAnyPointer()) { defaultOffset = field.getDefaultValueSchemaOffset(); } if (typeSchema.getBrandParameter() != nullptr) { kind = FieldKind::BRAND_PARAMETER; } else { kind = FieldKind::ANY_POINTER; switch (typeSchema.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::ANY_KIND: kind = FieldKind::ANY_POINTER; break; case schema::Type::AnyPointer::Unconstrained::STRUCT: kind = FieldKind::STRUCT; break; case schema::Type::AnyPointer::Unconstrained::LIST: kind = FieldKind::LIST; break; case schema::Type::AnyPointer::Unconstrained::CAPABILITY: kind = FieldKind::INTERFACE; break; } } break; } kj::String defaultMaskParam; if (defaultMask.size() > 0) { defaultMaskParam = kj::str(", ", defaultMask); } uint offset = slot.getOffset(); if (kind == FieldKind::PRIMITIVE) { return FieldText { kj::strTree( kj::mv(unionDiscrim.readerIsDecl), " inline ", type, " get", titleCase, "() const;\n" "\n"), kj::strTree( kj::mv(unionDiscrim.builderIsDecl), " inline ", type, " get", titleCase, "();\n" " inline void set", titleCase, "(", type, " value", setterDefault, ");\n" "\n"), kj::strTree(), kj::strTree( kj::mv(unionDiscrim.isDefs), templateContext.allDecls(), "inline ", type, " ", scope, "Reader::get", titleCase, "() const {\n", unionDiscrim.check, " return _reader.getDataField<", type, ">(\n" " ::capnp::bounded<", offset, ">() * ::capnp::ELEMENTS", defaultMaskParam, ");\n", "}\n" "\n", templateContext.allDecls(), "inline ", type, " ", scope, "Builder::get", titleCase, "() {\n", unionDiscrim.check, " return _builder.getDataField<", type, ">(\n" " ::capnp::bounded<", offset, ">() * ::capnp::ELEMENTS", defaultMaskParam, ");\n", "}\n", templateContext.allDecls(), "inline void ", scope, "Builder::set", titleCase, "(", type, " value) {\n", unionDiscrim.set, " _builder.setDataField<", type, ">(\n" " ::capnp::bounded<", offset, ">() * ::capnp::ELEMENTS, value", defaultMaskParam, ");\n", "}\n" "\n") }; } else if (kind == FieldKind::INTERFACE) { CppTypeName clientType = type; clientType.addMemberType("Client"); return FieldText { kj::strTree( kj::mv(unionDiscrim.readerIsDecl), " inline bool has", titleCase, "() const;\n" "#if !CAPNP_LITE\n" " inline ", clientType, " get", titleCase, "() const;\n" "#endif // !CAPNP_LITE\n" "\n"), kj::strTree( kj::mv(unionDiscrim.builderIsDecl), " inline bool has", titleCase, "();\n" "#if !CAPNP_LITE\n" " inline ", clientType, " get", titleCase, "();\n" " inline void set", titleCase, "(", clientType, "&& value);\n", " inline void set", titleCase, "(", clientType, "& value);\n", " inline void adopt", titleCase, "(::capnp::Orphan<", type, ">&& value);\n" " inline ::capnp::Orphan<", type, "> disown", titleCase, "();\n" "#endif // !CAPNP_LITE\n" "\n"), kj::strTree( hasDiscriminantValue(proto) ? kj::strTree() : kj::strTree( " inline ", clientType, " get", titleCase, "();\n")), kj::strTree( kj::mv(unionDiscrim.isDefs), templateContext.allDecls(), "inline bool ", scope, "Reader::has", titleCase, "() const {\n", unionDiscrim.has, " return !_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n", templateContext.allDecls(), "inline bool ", scope, "Builder::has", titleCase, "() {\n", unionDiscrim.has, " return !_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n" "#if !CAPNP_LITE\n", templateContext.allDecls(), "inline ", clientType, " ", scope, "Reader::get", titleCase, "() const {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::get(_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n", templateContext.allDecls(), "inline ", clientType, " ", scope, "Builder::get", titleCase, "() {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::get(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n", hasDiscriminantValue(proto) ? kj::strTree() : kj::strTree( templateContext.allDecls(), "inline ", clientType, " ", scope, "Pipeline::get", titleCase, "() {\n", " return ", clientType, "(_typeless.getPointerField(", offset, ").asCap());\n" "}\n"), templateContext.allDecls(), "inline void ", scope, "Builder::set", titleCase, "(", clientType, "&& cap) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::set(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), kj::mv(cap));\n" "}\n", templateContext.allDecls(), "inline void ", scope, "Builder::set", titleCase, "(", clientType, "& cap) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::set(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), cap);\n" "}\n", templateContext.allDecls(), "inline void ", scope, "Builder::adopt", titleCase, "(\n" " ::capnp::Orphan<", type, ">&& value) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::adopt(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), kj::mv(value));\n" "}\n", templateContext.allDecls(), "inline ::capnp::Orphan<", type, "> ", scope, "Builder::disown", titleCase, "() {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::disown(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n" "#endif // !CAPNP_LITE\n" "\n") }; } else if (kind == FieldKind::ANY_POINTER) { return FieldText { kj::strTree( kj::mv(unionDiscrim.readerIsDecl), " inline bool has", titleCase, "() const;\n" " inline ::capnp::AnyPointer::Reader get", titleCase, "() const;\n" "\n"), kj::strTree( kj::mv(unionDiscrim.builderIsDecl), " inline bool has", titleCase, "();\n" " inline ::capnp::AnyPointer::Builder get", titleCase, "();\n" " inline ::capnp::AnyPointer::Builder init", titleCase, "();\n" "\n"), kj::strTree(), kj::strTree( kj::mv(unionDiscrim.isDefs), templateContext.allDecls(), "inline bool ", scope, "Reader::has", titleCase, "() const {\n", unionDiscrim.has, " return !_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n", templateContext.allDecls(), "inline bool ", scope, "Builder::has", titleCase, "() {\n", unionDiscrim.has, " return !_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n", templateContext.allDecls(), "inline ::capnp::AnyPointer::Reader ", scope, "Reader::get", titleCase, "() const {\n", unionDiscrim.check, " return ::capnp::AnyPointer::Reader(_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n", templateContext.allDecls(), "inline ::capnp::AnyPointer::Builder ", scope, "Builder::get", titleCase, "() {\n", unionDiscrim.check, " return ::capnp::AnyPointer::Builder(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n", templateContext.allDecls(), "inline ::capnp::AnyPointer::Builder ", scope, "Builder::init", titleCase, "() {\n", unionDiscrim.set, " auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" " result.clear();\n" " return result;\n" "}\n" "\n") }; } else { // Blob, struct, list, or template param. These have only minor differences. uint64_t typeId = field.getContainingStruct().getProto().getId(); kj::String defaultParam = defaultOffset == 0 ? kj::str() : kj::str( ",\n ::capnp::schemas::bp_", kj::hex(typeId), " + ", defaultOffset, defaultSize == 0 ? kj::strTree() : kj::strTree(", ", defaultSize)); bool shouldIncludeStructInit = kind == FieldKind::STRUCT || kind == FieldKind::BRAND_PARAMETER; bool shouldIncludeSizedInit = kind != FieldKind::STRUCT || kind == FieldKind::BRAND_PARAMETER; bool shouldIncludePipelineGetter = !hasDiscriminantValue(proto) && (kind == FieldKind::STRUCT || kind == FieldKind::BRAND_PARAMETER); bool shouldIncludeArrayInitializer = false; bool shouldExcludeInLiteMode = type.hasInterfaces(); bool shouldTemplatizeInit = typeSchema.which() == schema::Type::ANY_POINTER && kind != FieldKind::BRAND_PARAMETER; CppTypeName elementReaderType; if (typeSchema.isList()) { bool primitiveElement = false; bool interface = false; auto elementType = typeSchema.asList().getElementType(); switch (elementType.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: primitiveElement = true; shouldIncludeArrayInitializer = true; break; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: primitiveElement = false; shouldIncludeArrayInitializer = true; break; case schema::Type::ANY_POINTER: primitiveElement = false; shouldIncludeArrayInitializer = elementType.getBrandParameter() != nullptr; break; case schema::Type::INTERFACE: primitiveElement = false; interface = true; break; case schema::Type::STRUCT: primitiveElement = false; break; } elementReaderType = typeName(elementType, nullptr); if (!primitiveElement) { if (interface) { elementReaderType.addMemberType("Client"); } else { elementReaderType.addMemberType("Reader"); } } }; CppTypeName readerType; CppTypeName builderType; CppTypeName pipelineType; if (kind == FieldKind::BRAND_PARAMETER) { readerType = CppTypeName::makeNamespace("capnp"); readerType.addMemberTemplate("ReaderFor", kj::heapArray(&type, 1)); builderType = CppTypeName::makeNamespace("capnp"); builderType.addMemberTemplate("BuilderFor", kj::heapArray(&type, 1)); pipelineType = CppTypeName::makeNamespace("capnp"); pipelineType.addMemberTemplate("PipelineFor", kj::heapArray(&type, 1)); } else { readerType = type; readerType.addMemberType("Reader"); builderType = type; builderType.addMemberType("Builder"); pipelineType = type; pipelineType.addMemberType("Pipeline"); } #define COND(cond, ...) ((cond) ? kj::strTree(__VA_ARGS__) : kj::strTree()) return FieldText { kj::strTree( kj::mv(unionDiscrim.readerIsDecl), " inline bool has", titleCase, "() const;\n", COND(shouldExcludeInLiteMode, "#if !CAPNP_LITE\n"), " inline ", readerType, " get", titleCase, "() const;\n", COND(shouldExcludeInLiteMode, "#endif // !CAPNP_LITE\n"), "\n"), kj::strTree( kj::mv(unionDiscrim.builderIsDecl), " inline bool has", titleCase, "();\n", COND(shouldExcludeInLiteMode, "#if !CAPNP_LITE\n"), " inline ", builderType, " get", titleCase, "();\n" " inline void set", titleCase, "(", readerType, " value);\n", COND(shouldIncludeArrayInitializer, " inline void set", titleCase, "(::kj::ArrayPtr value);\n"), COND(shouldIncludeStructInit, COND(shouldTemplatizeInit, " template \n" " inline ::capnp::BuilderFor init", titleCase, "As();\n"), COND(!shouldTemplatizeInit, " inline ", builderType, " init", titleCase, "();\n")), COND(shouldIncludeSizedInit, COND(shouldTemplatizeInit, " template \n" " inline ::capnp::BuilderFor init", titleCase, "As(unsigned int size);\n"), COND(!shouldTemplatizeInit, " inline ", builderType, " init", titleCase, "(unsigned int size);\n")), " inline void adopt", titleCase, "(::capnp::Orphan<", type, ">&& value);\n" " inline ::capnp::Orphan<", type, "> disown", titleCase, "();\n", COND(shouldExcludeInLiteMode, "#endif // !CAPNP_LITE\n"), "\n"), kj::strTree( COND(shouldIncludePipelineGetter, " inline ", pipelineType, " get", titleCase, "();\n")), kj::strTree( kj::mv(unionDiscrim.isDefs), templateContext.allDecls(), "inline bool ", scope, "Reader::has", titleCase, "() const {\n", unionDiscrim.has, " return !_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n", templateContext.allDecls(), "inline bool ", scope, "Builder::has", titleCase, "() {\n", unionDiscrim.has, " return !_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS).isNull();\n" "}\n", COND(shouldExcludeInLiteMode, "#if !CAPNP_LITE\n"), templateContext.allDecls(), "inline ", readerType, " ", scope, "Reader::get", titleCase, "() const {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::get(_reader.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS)", defaultParam, ");\n" "}\n", templateContext.allDecls(), "inline ", builderType, " ", scope, "Builder::get", titleCase, "() {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::get(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS)", defaultParam, ");\n" "}\n", COND(shouldIncludePipelineGetter, "#if !CAPNP_LITE\n", templateContext.allDecls(), "inline ", pipelineType, " ", scope, "Pipeline::get", titleCase, "() {\n", " return ", pipelineType, "(_typeless.getPointerField(", offset, "));\n" "}\n" "#endif // !CAPNP_LITE\n"), templateContext.allDecls(), "inline void ", scope, "Builder::set", titleCase, "(", readerType, " value) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::set(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), value);\n" "}\n", COND(shouldIncludeArrayInitializer, templateContext.allDecls(), "inline void ", scope, "Builder::set", titleCase, "(::kj::ArrayPtr value) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::set(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), value);\n" "}\n"), COND(shouldIncludeStructInit, COND(shouldTemplatizeInit, templateContext.allDecls(), "template \n" "inline ::capnp::BuilderFor ", scope, "Builder::init", titleCase, "As() {\n", " static_assert(::capnp::kind() == ::capnp::Kind::STRUCT,\n" " \"", proto.getName(), " must be a struct\");\n", unionDiscrim.set, " return ::capnp::_::PointerHelpers::init(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n"), COND(!shouldTemplatizeInit, templateContext.allDecls(), "inline ", builderType, " ", scope, "Builder::init", titleCase, "() {\n", unionDiscrim.set, " return ::capnp::_::PointerHelpers<", type, ">::init(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n")), COND(shouldIncludeSizedInit, COND(shouldTemplatizeInit, templateContext.allDecls(), "template \n" "inline ::capnp::BuilderFor ", scope, "Builder::init", titleCase, "As(unsigned int size) {\n", " static_assert(::capnp::kind() == ::capnp::Kind::LIST,\n" " \"", proto.getName(), " must be a list\");\n", unionDiscrim.set, " return ::capnp::_::PointerHelpers::init(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), size);\n" "}\n"), COND(!shouldTemplatizeInit, templateContext.allDecls(), "inline ", builderType, " ", scope, "Builder::init", titleCase, "(unsigned int size) {\n", unionDiscrim.set, " return ::capnp::_::PointerHelpers<", type, ">::init(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), size);\n" "}\n")), templateContext.allDecls(), "inline void ", scope, "Builder::adopt", titleCase, "(\n" " ::capnp::Orphan<", type, ">&& value) {\n", unionDiscrim.set, " ::capnp::_::PointerHelpers<", type, ">::adopt(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS), kj::mv(value));\n" "}\n", COND(type.hasDisambiguatedTemplate(), "#if !defined(_MSC_VER) || defined(__clang__)\n" "// Excluded under MSVC because bugs may make it unable to compile this method.\n"), templateContext.allDecls(), "inline ::capnp::Orphan<", type, "> ", scope, "Builder::disown", titleCase, "() {\n", unionDiscrim.check, " return ::capnp::_::PointerHelpers<", type, ">::disown(_builder.getPointerField(\n" " ::capnp::bounded<", offset, ">() * ::capnp::POINTERS));\n" "}\n", COND(type.hasDisambiguatedTemplate(), "#endif // !_MSC_VER || __clang__\n"), COND(shouldExcludeInLiteMode, "#endif // !CAPNP_LITE\n"), "\n") }; #undef COND } } // ----------------------------------------------------------------- enum class AsGenericRole { READER, BUILDER, CLIENT }; kj::StringTree makeAsGenericDef(AsGenericRole role, const TemplateContext& templateContext, kj::StringPtr type, kj::String innerType = kj::String()) { if (!templateContext.isGeneric()) { return kj::StringTree(); } kj::StringTree self, up; if (templateContext.hasParams()) { auto returnType = [&]() { return kj::strTree(type, templateContext.args("2"), innerType); }; kj::StringTree asGeneric = kj::strTree("as", innerType.size() ? type : "", "Generic()"); switch (role) { case AsGenericRole::READER: self = kj::strTree( " ", templateContext.decl(true, "2"), " typename ", returnType(), "::Reader ", kj::mv(asGeneric), " {\n" " return typename ", returnType(), "::Reader(_reader);\n" " }\n" "\n"); break; case AsGenericRole::BUILDER: self = kj::strTree( " ", templateContext.decl(true, "2"), " typename ", returnType(), "::Builder ", kj::mv(asGeneric), " {\n" " return typename ", returnType(), "::Builder(_builder);\n" " }\n" "\n"); break; case AsGenericRole::CLIENT: self = kj::strTree( " ", templateContext.decl(true, "2"), " typename ", returnType(), "::Client ", kj::mv(asGeneric), " {\n" " return castAs<", innerType.size() ? "typename " : "", returnType(), ">();\n" " }\n" "\n"); break; } } KJ_IF_MAYBE(p, templateContext.getParent()) { up = makeAsGenericDef(role, *p, p->getName(), kj::strTree( templateContext.hasParams() ? "::template " : "::", type, templateContext.args()).flatten()); } return kj::strTree(kj::mv(self), kj::mv(up)); } // ----------------------------------------------------------------- struct StructText { kj::StringTree outerTypeDecl; kj::StringTree outerTypeDef; kj::StringTree readerBuilderDefs; kj::StringTree inlineMethodDefs; kj::StringTree sourceDefs; }; kj::StringTree makeReaderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, const TemplateContext& templateContext, bool isUnion, kj::Array&& methodDecls) { return kj::strTree( templateContext.allDecls(), "class ", fullName, "::Reader {\n" "public:\n" " typedef ", unqualifiedParentType, " Reads;\n" "\n" " Reader() = default;\n" " inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}\n" "\n" " inline ::capnp::MessageSize totalSize() const {\n" " return _reader.totalSize().asPublic();\n" " }\n" "\n" "#if !CAPNP_LITE\n" " inline ::kj::StringTree toString() const {\n" " return ::capnp::_::structString(_reader, *_capnpPrivate::brand());\n" " }\n" "#endif // !CAPNP_LITE\n" "\n", makeAsGenericDef(AsGenericRole::READER, templateContext, unqualifiedParentType), isUnion ? kj::strTree(" inline Which which() const;\n") : kj::strTree(), kj::mv(methodDecls), "private:\n" " ::capnp::_::StructReader _reader;\n" " template \n" " friend struct ::capnp::ToDynamic_;\n" " template \n" " friend struct ::capnp::_::PointerHelpers;\n" " template \n" " friend struct ::capnp::List;\n" " friend class ::capnp::MessageBuilder;\n" " friend class ::capnp::Orphanage;\n" "};\n" "\n"); } kj::StringTree makeBuilderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, const TemplateContext& templateContext, bool isUnion, kj::Array&& methodDecls) { return kj::strTree( templateContext.allDecls(), "class ", fullName, "::Builder {\n" "public:\n" " typedef ", unqualifiedParentType, " Builds;\n" "\n" " Builder() = delete; // Deleted to discourage incorrect usage.\n" " // You can explicitly initialize to nullptr instead.\n" " inline Builder(decltype(nullptr)) {}\n" " inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}\n" " inline operator Reader() const { return Reader(_builder.asReader()); }\n" " inline Reader asReader() const { return *this; }\n" "\n" " inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }\n" "#if !CAPNP_LITE\n" " inline ::kj::StringTree toString() const { return asReader().toString(); }\n" "#endif // !CAPNP_LITE\n" "\n", makeAsGenericDef(AsGenericRole::BUILDER, templateContext, unqualifiedParentType), isUnion ? kj::strTree(" inline Which which();\n") : kj::strTree(), kj::mv(methodDecls), "private:\n" " ::capnp::_::StructBuilder _builder;\n" " template \n" " friend struct ::capnp::ToDynamic_;\n" " friend class ::capnp::Orphanage;\n", " template \n" " friend struct ::capnp::_::PointerHelpers;\n" "};\n" "\n"); } kj::StringTree makePipelineDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, const TemplateContext& templateContext, bool isUnion, kj::Array&& methodDecls) { return kj::strTree( "#if !CAPNP_LITE\n", templateContext.allDecls(), "class ", fullName, "::Pipeline {\n" "public:\n" " typedef ", unqualifiedParentType, " Pipelines;\n" "\n" " inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}\n" " inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)\n" " : _typeless(kj::mv(typeless)) {}\n" "\n", kj::mv(methodDecls), "private:\n" " ::capnp::AnyPointer::Pipeline _typeless;\n" " friend class ::capnp::PipelineHook;\n" " template \n" " friend struct ::capnp::ToDynamic_;\n" "};\n" "#endif // !CAPNP_LITE\n" "\n"); } kj::StringTree makeGenericDeclarations(const TemplateContext& templateContext, bool hasBrandDependencies) { // Returns the declarations for the private members of a generic struct/interface; // paired with the definitions from makeGenericDefinitions(). return kj::strTree( " static const ::capnp::_::RawBrandedSchema::Scope brandScopes[];\n" " static const ::capnp::_::RawBrandedSchema::Binding brandBindings[];\n", (!hasBrandDependencies ? "" : " static const ::capnp::_::RawBrandedSchema::Dependency brandDependencies[];\n"), " static const ::capnp::_::RawBrandedSchema specificBrand;\n" " static constexpr ::capnp::_::RawBrandedSchema const* brand() { " "return ::capnp::_::ChooseBrand<_capnpPrivate, ", templateContext.allArgs(), ">::brand(); }\n"); } kj::StringTree makeGenericDefinitions( const TemplateContext& templateContext, kj::StringPtr fullName, kj::StringPtr hexId, BrandInitializerText brandInitializers) { // Returns the definitions for the members from makeGenericDeclarations(). bool hasBrandDependencies = (brandInitializers.dependencies.size() != 0); auto scopeCount = templateContext.getScopeMap().size(); auto dependencyCount = brandInitializers.dependencyCount; kj::String templates = kj::str(templateContext.allDecls()); return kj::strTree( templates, "const ::capnp::_::RawBrandedSchema::Scope ", fullName, "::_capnpPrivate::brandScopes[] = ", kj::mv(brandInitializers.scopes), ";\n", templates, "const ::capnp::_::RawBrandedSchema::Binding ", fullName, "::_capnpPrivate::brandBindings[] = ", kj::mv(brandInitializers.bindings), ";\n", (!hasBrandDependencies ? kj::strTree("") : kj::strTree( templates, "const ::capnp::_::RawBrandedSchema::Dependency ", fullName, "::_capnpPrivate::brandDependencies[] = ", kj::mv(brandInitializers.dependencies), ";\n")), templates, "const ::capnp::_::RawBrandedSchema ", fullName, "::_capnpPrivate::specificBrand = {\n", " &::capnp::schemas::s_", hexId, ", brandScopes, ", (!hasBrandDependencies ? "nullptr" : "brandDependencies"), ",\n", " ", scopeCount, ", ", dependencyCount, ", nullptr\n" "};\n"); } StructText makeStructText(kj::StringPtr scope, kj::StringPtr name, StructSchema schema, kj::Array nestedTypeDecls, const TemplateContext& templateContext) { auto proto = schema.getProto(); KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) { name = annotatedName->getText(); } auto fullName = kj::str(scope, name, templateContext.args()); auto subScope = kj::str(fullName, "::"); auto fieldTexts = KJ_MAP(f, schema.getFields()) { return makeFieldText(subScope, f, templateContext); }; auto structNode = proto.getStruct(); uint discrimOffset = structNode.getDiscriminantOffset(); auto hexId = kj::hex(proto.getId()); kj::String templates = kj::str(templateContext.allDecls()); // Ends with a newline // Private members struct kj::StringTree declareText = kj::strTree( " struct _capnpPrivate {\n" " CAPNP_DECLARE_STRUCT_HEADER(", hexId, ", ", structNode.getDataWordCount(), ", ", structNode.getPointerCount(), ")\n"); kj::StringTree defineText = kj::strTree( "// ", fullName, "\n", "#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n", templates, "constexpr uint16_t ", fullName, "::_capnpPrivate::dataWordSize;\n", templates, "constexpr uint16_t ", fullName, "::_capnpPrivate::pointerCount;\n", "#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n", "#if !CAPNP_LITE\n", "#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n", templates, "constexpr ::capnp::Kind ", fullName, "::_capnpPrivate::kind;\n", templates, "constexpr ::capnp::_::RawSchema const* ", fullName, "::_capnpPrivate::schema;\n", "#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n"); if (templateContext.isGeneric()) { auto brandInitializers = makeBrandInitializers(templateContext, schema); bool hasDeps = (brandInitializers.dependencies.size() != 0); declareText = kj::strTree(kj::mv(declareText), " #if !CAPNP_LITE\n", makeGenericDeclarations(templateContext, hasDeps), " #endif // !CAPNP_LITE\n"); defineText = kj::strTree(kj::mv(defineText), makeGenericDefinitions( templateContext, fullName, kj::str(hexId), kj::mv(brandInitializers))); } else { declareText = kj::strTree(kj::mv(declareText), " #if !CAPNP_LITE\n" " static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }\n" " #endif // !CAPNP_LITE\n"); } declareText = kj::strTree(kj::mv(declareText), " };"); defineText = kj::strTree(kj::mv(defineText), "#endif // !CAPNP_LITE\n\n"); // Name of the ::Which type, when applicable. CppTypeName whichName; if (structNode.getDiscriminantCount() != 0) { whichName = cppFullName(schema, nullptr); whichName.addMemberType("Which"); } return StructText { kj::strTree( templateContext.hasParams() ? " " : "", templateContext.decl(true), " struct ", name, ";\n"), kj::strTree( templateContext.parentDecls(), templateContext.decl(scope == nullptr), "struct ", scope, name, " {\n", " ", name, "() = delete;\n" "\n" " class Reader;\n" " class Builder;\n" " class Pipeline;\n", structNode.getDiscriminantCount() == 0 ? kj::strTree() : kj::strTree( " enum Which: uint16_t {\n", KJ_MAP(f, structNode.getFields()) { if (hasDiscriminantValue(f)) { return kj::strTree(" ", toUpperCase(protoName(f)), ",\n"); } else { return kj::strTree(); } }, " };\n"), KJ_MAP(n, nestedTypeDecls) { return kj::mv(n); }, "\n", kj::mv(declareText), "\n", "};\n" "\n"), kj::strTree( makeReaderDef(fullName, name, templateContext, structNode.getDiscriminantCount() != 0, KJ_MAP(f, fieldTexts) { return kj::mv(f.readerMethodDecls); }), makeBuilderDef(fullName, name, templateContext, structNode.getDiscriminantCount() != 0, KJ_MAP(f, fieldTexts) { return kj::mv(f.builderMethodDecls); }), makePipelineDef(fullName, name, templateContext, structNode.getDiscriminantCount() != 0, KJ_MAP(f, fieldTexts) { return kj::mv(f.pipelineMethodDecls); })), kj::strTree( structNode.getDiscriminantCount() == 0 ? kj::strTree() : kj::strTree( templateContext.allDecls(), "inline ", whichName, " ", fullName, "::Reader::which() const {\n" " return _reader.getDataField(\n" " ::capnp::bounded<", discrimOffset, ">() * ::capnp::ELEMENTS);\n" "}\n", templateContext.allDecls(), "inline ", whichName, " ", fullName, "::Builder::which() {\n" " return _builder.getDataField(\n" " ::capnp::bounded<", discrimOffset, ">() * ::capnp::ELEMENTS);\n" "}\n" "\n"), KJ_MAP(f, fieldTexts) { return kj::mv(f.inlineMethodDefs); }), kj::mv(defineText) }; } // ----------------------------------------------------------------- struct MethodText { kj::StringTree clientDecls; kj::StringTree serverDecls; kj::StringTree inlineDefs; kj::StringTree sourceDefs; kj::StringTree dispatchCase; }; MethodText makeMethodText(kj::StringPtr interfaceName, InterfaceSchema::Method method, const TemplateContext& templateContext) { auto proto = method.getProto(); auto name = protoName(proto); auto titleCase = toTitleCase(name); auto paramSchema = method.getParamType(); auto resultSchema = method.getResultType(); auto identifierName = safeIdentifier(name); auto paramProto = paramSchema.getProto(); auto resultProto = resultSchema.getProto(); bool isStreaming = method.isStreaming(); auto implicitParamsReader = proto.getImplicitParameters(); auto implicitParamsBuilder = kj::heapArrayBuilder(implicitParamsReader.size()); for (auto param: implicitParamsReader) { implicitParamsBuilder.add(CppTypeName::makeTemplateParam(param.getName())); } auto implicitParams = implicitParamsBuilder.finish(); kj::String implicitParamsTemplateDecl; if (implicitParams.size() > 0) { implicitParamsTemplateDecl = kj::str( "template <", kj::StringTree(KJ_MAP(p, implicitParams) { return kj::strTree("typename ", p); }, ", "), ">\n"); } CppTypeName interfaceTypeName = cppFullName(method.getContainingInterface(), nullptr); CppTypeName paramType; CppTypeName genericParamType; if (paramProto.getScopeId() == 0) { paramType = interfaceTypeName; if (implicitParams.size() == 0) { paramType.addMemberType(kj::str(titleCase, "Params")); genericParamType = paramType; } else { genericParamType = paramType; genericParamType.addMemberTemplate(kj::str(titleCase, "Params"), nullptr); paramType.addMemberTemplate(kj::str(titleCase, "Params"), kj::heapArray(implicitParams.asPtr())); } } else { paramType = cppFullName(paramSchema, method); genericParamType = cppFullName(paramSchema, nullptr); } CppTypeName resultType; CppTypeName genericResultType; if (isStreaming) { // We don't use resultType or genericResultType in this case. We want to avoid computing them // at all so that we don't end up marking stream.capnp.h in usedImports. } else if (resultProto.getScopeId() == 0) { resultType = interfaceTypeName; if (implicitParams.size() == 0) { resultType.addMemberType(kj::str(titleCase, "Results")); genericResultType = resultType; } else { genericResultType = resultType; genericResultType.addMemberTemplate(kj::str(titleCase, "Results"), nullptr); resultType.addMemberTemplate(kj::str(titleCase, "Results"), kj::heapArray(implicitParams.asPtr())); } } else { resultType = cppFullName(resultSchema, method); genericResultType = cppFullName(resultSchema, nullptr); } kj::String shortParamType = paramProto.getScopeId() == 0 ? kj::str(titleCase, "Params") : kj::str(genericParamType); kj::String shortResultType = resultProto.getScopeId() == 0 || isStreaming ? kj::str(titleCase, "Results") : kj::str(genericResultType); auto interfaceProto = method.getContainingInterface().getProto(); uint64_t interfaceId = interfaceProto.getId(); auto interfaceIdHex = kj::hex(interfaceId); uint16_t methodId = method.getIndex(); // TODO(msvc): Notice that the return type of this method's request function is supposed to be // `::capnp::Request`. If the first template parameter to ::capnp::Request is a // template instantiation, MSVC will sometimes complain that it's unspecialized and can't be // used as a parameter in the return type (error C3203). It is not clear to me under what exact // conditions this bug occurs, but it commonly crops up in test.capnp.h. // // The easiest (and only) workaround I found is to use C++14's return type deduction here, thus // the `CAPNP_AUTO_IF_MSVC()` hackery in the return type declarations below. We're depending on // the fact that that this function has an inline implementation for the deduction to work. bool noPromisePipelining = !resultSchema.mayContainCapabilities(); auto requestMethodImpl = kj::strTree( templateContext.allDecls(), implicitParamsTemplateDecl, templateContext.isGeneric() ? "CAPNP_AUTO_IF_MSVC(" : "", isStreaming ? kj::strTree("::capnp::StreamingRequest<", paramType, ">") : kj::strTree("::capnp::Request<", paramType, ", ", resultType, ">"), templateContext.isGeneric() ? ")\n" : "\n", interfaceName, "::Client::", name, "Request(::kj::Maybe< ::capnp::MessageSize> sizeHint) {\n", isStreaming ? kj::strTree(" return newStreamingCall<", paramType, ">(\n") : kj::strTree(" return newCall<", paramType, ", ", resultType, ">(\n"), " 0x", interfaceIdHex, "ull, ", methodId, ", sizeHint, {", noPromisePipelining, "});\n" "}\n"); bool allowCancellation = false; if (annotationValue(proto, ALLOW_CANCELLATION_ANNOTATION_ID) != nullptr) { allowCancellation = true; } else if (annotationValue(interfaceProto, ALLOW_CANCELLATION_ANNOTATION_ID) != nullptr) { allowCancellation = true; } else { schema::Node::Reader node = interfaceProto; while (!node.isFile()) { node = schemaLoader.get(node.getScopeId()).getProto(); } if (annotationValue(node, ALLOW_CANCELLATION_ANNOTATION_ID) != nullptr) { allowCancellation = true; } } return MethodText { kj::strTree( implicitParamsTemplateDecl.size() == 0 ? "" : " ", implicitParamsTemplateDecl, templateContext.isGeneric() ? " CAPNP_AUTO_IF_MSVC(" : " ", isStreaming ? kj::strTree("::capnp::StreamingRequest<", paramType, ">") : kj::strTree("::capnp::Request<", paramType, ", ", resultType, ">"), templateContext.isGeneric() ? ")" : "", " ", name, "Request(\n" " ::kj::Maybe< ::capnp::MessageSize> sizeHint = nullptr);\n"), kj::strTree( paramProto.getScopeId() != 0 ? kj::strTree() : kj::strTree( " typedef ", genericParamType, " ", titleCase, "Params;\n"), resultProto.getScopeId() != 0 ? kj::strTree() : kj::strTree( " typedef ", genericResultType, " ", titleCase, "Results;\n"), isStreaming ? kj::strTree(" typedef ::capnp::StreamingCallContext<", shortParamType, "> ") : kj::strTree( " typedef ::capnp::CallContext<", shortParamType, ", ", shortResultType, "> "), titleCase, "Context;\n" " virtual ::kj::Promise ", identifierName, "(", titleCase, "Context context);\n"), implicitParams.size() == 0 ? kj::strTree() : kj::mv(requestMethodImpl), kj::strTree( implicitParams.size() == 0 ? kj::mv(requestMethodImpl) : kj::strTree(), templateContext.allDecls(), "::kj::Promise ", interfaceName, "::Server::", identifierName, "(", titleCase, "Context) {\n" " return ::capnp::Capability::Server::internalUnimplemented(\n" " \"", interfaceProto.getDisplayName(), "\", \"", name, "\",\n" " 0x", interfaceIdHex, "ull, ", methodId, ");\n" "}\n"), kj::strTree( " case ", methodId, ":\n", isStreaming ? kj::strTree( // For streaming calls, we need to add an evalNow() here so that exceptions thrown // directly from the call can propagate to later calls. If we don't capture the // exception properly then the caller will never find out that this is a streaming // call (indicated by the boolean in the return value) so won't know to propagate // the exception. " return {\n" " kj::evalNow([&]() {\n" " return ", identifierName, "(::capnp::Capability::Server::internalGetTypedStreamingContext<\n" " ", genericParamType, ">(context));\n" " }),\n" " true,\n" " ", allowCancellation, "\n" " };\n") : kj::strTree( // For non-streaming calls we let exceptions just flow through for a little more // efficiency. " return {\n" " ", identifierName, "(::capnp::Capability::Server::internalGetTypedContext<\n" " ", genericParamType, ", ", genericResultType, ">(context)),\n" " false,\n" " ", allowCancellation, "\n" " };\n")) }; } struct InterfaceText { kj::StringTree outerTypeDecl; kj::StringTree outerTypeDef; kj::StringTree clientServerDefs; kj::StringTree inlineMethodDefs; kj::StringTree sourceDefs; }; struct ExtendInfo { CppTypeName typeName; uint64_t id; }; void getTransitiveSuperclasses(InterfaceSchema schema, std::map& map) { if (map.insert(std::make_pair(schema.getProto().getId(), schema)).second) { for (auto sup: schema.getSuperclasses()) { getTransitiveSuperclasses(sup, map); } } } InterfaceText makeInterfaceText(kj::StringPtr scope, kj::StringPtr name, InterfaceSchema schema, kj::Array nestedTypeDecls, const TemplateContext& templateContext) { auto fullName = kj::str(scope, name, templateContext.args()); auto methods = KJ_MAP(m, schema.getMethods()) { return makeMethodText(fullName, m, templateContext); }; auto proto = schema.getProto(); auto hexId = kj::hex(proto.getId()); auto superclasses = KJ_MAP(superclass, schema.getSuperclasses()) { return ExtendInfo { cppFullName(superclass, nullptr), superclass.getProto().getId() }; }; kj::Array transitiveSuperclasses; { std::map map; getTransitiveSuperclasses(schema, map); map.erase(schema.getProto().getId()); transitiveSuperclasses = KJ_MAP(entry, map) { return ExtendInfo { cppFullName(entry.second, nullptr), entry.second.getProto().getId() }; }; } CppTypeName typeName = cppFullName(schema, nullptr); CppTypeName clientName = typeName; clientName.addMemberType("Client"); kj::String templates = kj::str(templateContext.allDecls()); // Ends with a newline // Private members struct kj::StringTree declareText = kj::strTree( " #if !CAPNP_LITE\n" " struct _capnpPrivate {\n" " CAPNP_DECLARE_INTERFACE_HEADER(", hexId, ")\n"); kj::StringTree defineText = kj::strTree( "// ", fullName, "\n", "#if !CAPNP_LITE\n", "#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n", templates, "constexpr ::capnp::Kind ", fullName, "::_capnpPrivate::kind;\n", templates, "constexpr ::capnp::_::RawSchema const* ", fullName, "::_capnpPrivate::schema;\n" "#endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n"); if (templateContext.isGeneric()) { auto brandInitializers = makeBrandInitializers(templateContext, schema); bool hasDeps = (brandInitializers.dependencies.size() != 0); declareText = kj::strTree(kj::mv(declareText), makeGenericDeclarations(templateContext, hasDeps)); defineText = kj::strTree(kj::mv(defineText), makeGenericDefinitions( templateContext, fullName, kj::str(hexId), kj::mv(brandInitializers))); } else { declareText = kj::strTree(kj::mv(declareText), " static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }\n"); } declareText = kj::strTree(kj::mv(declareText), " };\n #endif // !CAPNP_LITE"); defineText = kj::strTree(kj::mv(defineText), "#endif // !CAPNP_LITE\n\n"); return InterfaceText { kj::strTree( templateContext.hasParams() ? " " : "", templateContext.decl(true), " struct ", name, ";\n"), kj::strTree( templateContext.parentDecls(), templateContext.decl(scope == nullptr), "struct ", scope, name, " {\n", " ", name, "() = delete;\n" "\n" "#if !CAPNP_LITE\n" " class Client;\n" " class Server;\n" "#endif // !CAPNP_LITE\n" "\n", KJ_MAP(n, nestedTypeDecls) { return kj::mv(n); }, "\n", kj::mv(declareText), "\n" "};\n" "\n"), kj::strTree( "#if !CAPNP_LITE\n", templateContext.allDecls(), "class ", fullName, "::Client\n" " : public virtual ::capnp::Capability::Client", KJ_MAP(s, superclasses) { return kj::strTree(",\n public virtual ", s.typeName.strNoTypename(), "::Client"); }, " {\n" "public:\n" " typedef ", name, " Calls;\n" " typedef ", name, " Reads;\n" "\n" " Client(decltype(nullptr));\n" " explicit Client(::kj::Own< ::capnp::ClientHook>&& hook);\n" " template ()>>\n" " Client(::kj::Own<_t>&& server);\n" " template ()>>\n" " Client(::kj::Promise<_t>&& promise);\n" " Client(::kj::Exception&& exception);\n" " Client(Client&) = default;\n" " Client(Client&&) = default;\n" " Client& operator=(Client& other);\n" " Client& operator=(Client&& other);\n" "\n", makeAsGenericDef(AsGenericRole::CLIENT, templateContext, name), KJ_MAP(m, methods) { return kj::mv(m.clientDecls); }, "\n" "protected:\n" " Client() = default;\n" "};\n" "\n", templateContext.allDecls(), "class ", fullName, "::Server\n" " : public virtual ::capnp::Capability::Server", KJ_MAP(s, superclasses) { return kj::strTree(",\n public virtual ", s.typeName.strNoTypename(), "::Server"); }, " {\n" "public:\n", " typedef ", name, " Serves;\n" "\n" " ::capnp::Capability::Server::DispatchCallResult dispatchCall(\n" " uint64_t interfaceId, uint16_t methodId,\n" " ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context)\n" " override;\n" "\n" "protected:\n", KJ_MAP(m, methods) { return kj::mv(m.serverDecls); }, "\n" " inline ", clientName, " thisCap() {\n" " return ::capnp::Capability::Server::thisCap()\n" " .template castAs<", typeName, ">();\n" " }\n" "\n" " ::capnp::Capability::Server::DispatchCallResult dispatchCallInternal(\n" " uint16_t methodId,\n" " ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context);\n" "};\n" "#endif // !CAPNP_LITE\n" "\n"), kj::strTree( "#if !CAPNP_LITE\n", templateContext.allDecls(), "inline ", fullName, "::Client::Client(decltype(nullptr))\n" " : ::capnp::Capability::Client(nullptr) {}\n", templateContext.allDecls(), "inline ", fullName, "::Client::Client(\n" " ::kj::Own< ::capnp::ClientHook>&& hook)\n" " : ::capnp::Capability::Client(::kj::mv(hook)) {}\n", templateContext.allDecls(), "template \n" "inline ", fullName, "::Client::Client(::kj::Own<_t>&& server)\n" " : ::capnp::Capability::Client(::kj::mv(server)) {}\n", templateContext.allDecls(), "template \n" "inline ", fullName, "::Client::Client(::kj::Promise<_t>&& promise)\n" " : ::capnp::Capability::Client(::kj::mv(promise)) {}\n", templateContext.allDecls(), "inline ", fullName, "::Client::Client(::kj::Exception&& exception)\n" " : ::capnp::Capability::Client(::kj::mv(exception)) {}\n", templateContext.allDecls(), "inline ", clientName, "& ", fullName, "::Client::operator=(Client& other) {\n" " ::capnp::Capability::Client::operator=(other);\n" " return *this;\n" "}\n", templateContext.allDecls(), "inline ", clientName, "& ", fullName, "::Client::operator=(Client&& other) {\n" " ::capnp::Capability::Client::operator=(kj::mv(other));\n" " return *this;\n" "}\n" "\n", KJ_MAP(m, methods) { return kj::mv(m.inlineDefs); }, "#endif // !CAPNP_LITE\n"), kj::strTree( "#if !CAPNP_LITE\n", KJ_MAP(m, methods) { return kj::mv(m.sourceDefs); }, templateContext.allDecls(), "::capnp::Capability::Server::DispatchCallResult ", fullName, "::Server::dispatchCall(\n" " uint64_t interfaceId, uint16_t methodId,\n" " ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context) {\n" " switch (interfaceId) {\n" " case 0x", kj::hex(proto.getId()), "ull:\n" " return dispatchCallInternal(methodId, context);\n", KJ_MAP(s, transitiveSuperclasses) { return kj::strTree( " case 0x", kj::hex(s.id), "ull:\n" " return ", s.typeName.strNoTypename(), "::Server::dispatchCallInternal(methodId, context);\n"); }, " default:\n" " return internalUnimplemented(\"", proto.getDisplayName(), "\", interfaceId);\n" " }\n" "}\n", templateContext.allDecls(), "::capnp::Capability::Server::DispatchCallResult ", fullName, "::Server::dispatchCallInternal(\n" " uint16_t methodId,\n" " ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context) {\n" " switch (methodId) {\n", KJ_MAP(m, methods) { return kj::mv(m.dispatchCase); }, " default:\n" " (void)context;\n" " return ::capnp::Capability::Server::internalUnimplemented(\n" " \"", proto.getDisplayName(), "\",\n" " 0x", kj::hex(proto.getId()), "ull, methodId);\n" " }\n" "}\n" "#endif // !CAPNP_LITE\n" "\n", kj::mv(defineText)) }; } // ----------------------------------------------------------------- struct ConstText { bool needsSchema; kj::StringTree decl; kj::StringTree def; }; ConstText makeConstText(kj::StringPtr scope, kj::StringPtr name, ConstSchema schema, const TemplateContext& templateContext) { auto proto = schema.getProto(); auto constProto = proto.getConst(); auto type = schema.getType(); auto typeName_ = typeName(type, nullptr); auto upperCase = toUpperCase(name); // Linkage qualifier for non-primitive types. const char* linkage = scope.size() == 0 ? "extern " : "static "; switch (type.which()) { case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::ENUM: return ConstText { false, kj::strTree("static constexpr ", typeName_, ' ', upperCase, " = ", literalValue(schema.getType(), constProto.getValue()), ";\n"), scope.size() == 0 ? kj::strTree() : kj::strTree( "#if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL\n" "constexpr ", typeName_, ' ', scope, upperCase, ";\n" "#endif\n") }; case schema::Type::VOID: case schema::Type::FLOAT32: case schema::Type::FLOAT64: { // TODO(msvc): MSVC doesn't like float- or class-typed constexprs. As soon as this is fixed, // treat VOID, FLOAT32, and FLOAT64 the same as the other primitives. kj::String value = literalValue(schema.getType(), constProto.getValue()).flatten(); return ConstText { false, kj::strTree("static KJ_CONSTEXPR(const) ", typeName_, ' ', upperCase, " CAPNP_NON_INT_CONSTEXPR_DECL_INIT(", value, ");\n"), scope.size() == 0 ? kj::strTree() : kj::strTree( "KJ_CONSTEXPR(const) ", typeName_, ' ', scope, upperCase, " CAPNP_NON_INT_CONSTEXPR_DEF_INIT(", value, ");\n") }; } case schema::Type::TEXT: { kj::String constType = kj::strTree( "::capnp::_::ConstText<", schema.as().size(), ">").flatten(); return ConstText { true, kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"), kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_", kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n") }; } case schema::Type::DATA: { kj::String constType = kj::strTree( "::capnp::_::ConstData<", schema.as().size(), ">").flatten(); return ConstText { true, kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"), kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_", kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n") }; } case schema::Type::STRUCT: { kj::String constType = kj::strTree( "::capnp::_::ConstStruct<", typeName_, ">").flatten(); return ConstText { true, kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"), kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_", kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n") }; } case schema::Type::LIST: { kj::String constType = kj::strTree( "::capnp::_::ConstList<", typeName(type.asList().getElementType(), nullptr), ">") .flatten(); return ConstText { true, kj::strTree(linkage, "const ", constType, ' ', upperCase, ";\n"), kj::strTree("const ", constType, ' ', scope, upperCase, "(::capnp::schemas::b_", kj::hex(proto.getId()), ".words + ", schema.getValueSchemaOffset(), ");\n") }; } case schema::Type::ANY_POINTER: case schema::Type::INTERFACE: return ConstText { false, kj::strTree(), kj::strTree() }; } KJ_UNREACHABLE; } // ----------------------------------------------------------------- struct NodeText { kj::StringTree outerTypeDecl; kj::StringTree outerTypeDef; kj::StringTree readerBuilderDefs; kj::StringTree inlineMethodDefs; kj::StringTree capnpSchemaDecls; kj::StringTree capnpSchemaDefs; kj::StringTree sourceFileDefs; }; NodeText makeNodeText(kj::StringPtr namespace_, kj::StringPtr scope, kj::StringPtr name, Schema schema, const TemplateContext& parentTemplateContext) { // `templateContext` is something like "template \ntemplate \n" // declaring template parameters for all parent scopes. auto proto = schema.getProto(); KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) { name = annotatedName->getText(); } auto hexId = kj::hex(proto.getId()); TemplateContext templateContext(parentTemplateContext, name, proto); auto subScope = kj::str(scope, name, templateContext.args(), "::"); // Compute nested nodes, including groups. kj::Vector nestedTexts(proto.getNestedNodes().size()); for (auto nested: proto.getNestedNodes()) { nestedTexts.add(makeNodeText( namespace_, subScope, nested.getName(), schemaLoader.getUnbound(nested.getId()),\ templateContext)); }; if (proto.isStruct()) { for (auto field: proto.getStruct().getFields()) { if (field.isGroup()) { nestedTexts.add(makeNodeText( namespace_, subScope, toTitleCase(protoName(field)), schemaLoader.getUnbound(field.getGroup().getTypeId()), templateContext)); } } } else if (proto.isInterface()) { for (auto method: proto.getInterface().getMethods()) { { Schema params = schemaLoader.getUnbound(method.getParamStructType()); auto paramsProto = schemaLoader.getUnbound(method.getParamStructType()).getProto(); if (paramsProto.getScopeId() == 0) { nestedTexts.add(makeNodeText(namespace_, subScope, toTitleCase(kj::str(protoName(method), "Params")), params, templateContext)); } } { Schema results = schemaLoader.getUnbound(method.getResultStructType()); auto resultsProto = schemaLoader.getUnbound(method.getResultStructType()).getProto(); if (resultsProto.getScopeId() == 0) { nestedTexts.add(makeNodeText(namespace_, subScope, toTitleCase(kj::str(protoName(method), "Results")), results, templateContext)); } } } } // Convert the encoded schema to a literal byte array. kj::ArrayPtr rawSchema = schema.asUncheckedMessage(); auto schemaLiteral = kj::StringTree(KJ_MAP(w, rawSchema) { const byte* bytes = reinterpret_cast(&w); return kj::strTree(KJ_MAP(i, kj::range(0, sizeof(word))) { auto text = kj::toCharSequence(kj::implicitCast(bytes[i])); return kj::strTree(kj::repeat(' ', 4 - text.size()), text, ","); }); }, "\n "); auto schemaDecl = kj::strTree( "CAPNP_DECLARE_SCHEMA(", hexId, ");\n"); std::set deps; enumerateDeps(proto, deps); kj::Array membersByName; kj::Array membersByDiscrim; switch (proto.which()) { case schema::Node::STRUCT: { auto structSchema = schema.asStruct(); membersByName = makeMembersByName(structSchema.getFields()); auto builder = kj::heapArrayBuilder(structSchema.getFields().size()); for (auto field: structSchema.getUnionFields()) { builder.add(field.getIndex()); } for (auto field: structSchema.getNonUnionFields()) { builder.add(field.getIndex()); } membersByDiscrim = builder.finish(); break; } case schema::Node::ENUM: membersByName = makeMembersByName(schema.asEnum().getEnumerants()); break; case schema::Node::INTERFACE: membersByName = makeMembersByName(schema.asInterface().getMethods()); break; default: break; } auto brandDeps = makeBrandDepInitializers( makeBrandDepMap(templateContext, schema.getGeneric())); bool mayContainCapabilities = proto.isStruct() && schema.asStruct().mayContainCapabilities(); auto schemaDef = kj::strTree( "static const ::capnp::_::AlignedData<", rawSchema.size(), "> b_", hexId, " = {\n" " {", kj::mv(schemaLiteral), " }\n" "};\n" "::capnp::word const* const bp_", hexId, " = b_", hexId, ".words;\n" "#if !CAPNP_LITE\n", deps.size() == 0 ? kj::strTree() : kj::strTree( "static const ::capnp::_::RawSchema* const d_", hexId, "[] = {\n", KJ_MAP(depId, deps) { return kj::strTree(" &s_", kj::hex(depId), ",\n"); }, "};\n"), membersByName.size() == 0 ? kj::strTree() : kj::strTree( "static const uint16_t m_", hexId, "[] = {", kj::StringTree(KJ_MAP(index, membersByName) { return kj::strTree(index); }, ", "), "};\n"), membersByDiscrim.size() == 0 ? kj::strTree() : kj::strTree( "static const uint16_t i_", hexId, "[] = {", kj::StringTree(KJ_MAP(index, membersByDiscrim) { return kj::strTree(index); }, ", "), "};\n"), brandDeps.size() == 0 ? kj::strTree() : kj::strTree( "KJ_CONSTEXPR(const) ::capnp::_::RawBrandedSchema::Dependency bd_", hexId, "[] = ", kj::mv(brandDeps), ";\n"), "const ::capnp::_::RawSchema s_", hexId, " = {\n" " 0x", hexId, ", b_", hexId, ".words, ", rawSchema.size(), ", ", deps.size() == 0 ? kj::strTree("nullptr") : kj::strTree("d_", hexId), ", ", membersByName.size() == 0 ? kj::strTree("nullptr") : kj::strTree("m_", hexId), ",\n", " ", deps.size(), ", ", membersByName.size(), ", ", membersByDiscrim.size() == 0 ? kj::strTree("nullptr") : kj::strTree("i_", hexId), ", nullptr, nullptr, { &s_", hexId, ", nullptr, ", brandDeps.size() == 0 ? kj::strTree("nullptr, 0, 0") : kj::strTree( "bd_", hexId, ", 0, " "sizeof(bd_", hexId, ") / sizeof(bd_", hexId, "[0])"), ", nullptr }, ", mayContainCapabilities, "\n" "};\n" "#endif // !CAPNP_LITE\n"); NodeText top = makeNodeTextWithoutNested( namespace_, scope, name, schema, KJ_MAP(n, nestedTexts) { return kj::mv(n.outerTypeDecl); }, templateContext); NodeText result = { kj::mv(top.outerTypeDecl), kj::strTree( kj::mv(top.outerTypeDef), KJ_MAP(n, nestedTexts) { return kj::mv(n.outerTypeDef); }), kj::strTree( kj::mv(top.readerBuilderDefs), KJ_MAP(n, nestedTexts) { return kj::mv(n.readerBuilderDefs); }), kj::strTree( kj::mv(top.inlineMethodDefs), KJ_MAP(n, nestedTexts) { return kj::mv(n.inlineMethodDefs); }), kj::strTree( kj::mv(schemaDecl), kj::mv(top.capnpSchemaDecls), KJ_MAP(n, nestedTexts) { return kj::mv(n.capnpSchemaDecls); }), kj::strTree( kj::mv(schemaDef), kj::mv(top.capnpSchemaDefs), KJ_MAP(n, nestedTexts) { return kj::mv(n.capnpSchemaDefs); }), kj::strTree( kj::mv(top.sourceFileDefs), KJ_MAP(n, nestedTexts) { return kj::mv(n.sourceFileDefs); }), }; if (templateContext.isGeneric()) { // This is a template, so move all source declarations into the header. result.inlineMethodDefs = kj::strTree( kj::mv(result.inlineMethodDefs), kj::mv(result.sourceFileDefs)); result.sourceFileDefs = kj::strTree(); } return result; } NodeText makeNodeTextWithoutNested(kj::StringPtr namespace_, kj::StringPtr scope, kj::StringPtr name, Schema schema, kj::Array nestedTypeDecls, const TemplateContext& templateContext) { auto proto = schema.getProto(); KJ_IF_MAYBE(annotatedName, annotationValue(proto, NAME_ANNOTATION_ID)) { name = annotatedName->getText(); } auto hexId = kj::hex(proto.getId()); switch (proto.which()) { case schema::Node::FILE: KJ_FAIL_REQUIRE("This method shouldn't be called on file nodes."); case schema::Node::STRUCT: { StructText structText = makeStructText(scope, name, schema.asStruct(), kj::mv(nestedTypeDecls), templateContext); return NodeText { kj::mv(structText.outerTypeDecl), kj::mv(structText.outerTypeDef), kj::mv(structText.readerBuilderDefs), kj::mv(structText.inlineMethodDefs), kj::strTree(), kj::strTree(), kj::mv(structText.sourceDefs), }; } case schema::Node::ENUM: { auto enumerants = schema.asEnum().getEnumerants(); return NodeText { scope.size() == 0 ? kj::strTree() : kj::strTree( " typedef ::capnp::schemas::", name, "_", hexId, " ", name, ";\n" "\n"), scope.size() > 0 ? kj::strTree() : kj::strTree( "typedef ::capnp::schemas::", name, "_", hexId, " ", name, ";\n" "\n"), kj::strTree(), kj::strTree(), kj::strTree( // We declare enums in the capnp::schemas namespace and then typedef them into // place because we don't want them to be parameterized for generics. "enum class ", name, "_", hexId, ": uint16_t {\n", KJ_MAP(e, enumerants) { return kj::strTree(" ", toUpperCase(protoName(e.getProto())), ",\n"); }, "};\n" "CAPNP_DECLARE_ENUM(", name, ", ", hexId, ");\n"), kj::strTree( "CAPNP_DEFINE_ENUM(", name, "_", hexId, ", ", hexId, ");\n"), kj::strTree(), }; } case schema::Node::INTERFACE: { hasInterfaces = true; InterfaceText interfaceText = makeInterfaceText(scope, name, schema.asInterface(), kj::mv(nestedTypeDecls), templateContext); return NodeText { kj::mv(interfaceText.outerTypeDecl), kj::mv(interfaceText.outerTypeDef), kj::mv(interfaceText.clientServerDefs), kj::mv(interfaceText.inlineMethodDefs), kj::strTree(), kj::strTree(), kj::mv(interfaceText.sourceDefs), }; } case schema::Node::CONST: { auto constText = makeConstText(scope, name, schema.asConst(), templateContext); return NodeText { scope.size() == 0 ? kj::strTree() : kj::strTree(" ", kj::mv(constText.decl)), scope.size() > 0 ? kj::strTree() : kj::mv(constText.decl), kj::strTree(), kj::strTree(), kj::strTree(), kj::strTree(), kj::mv(constText.def), }; } case schema::Node::ANNOTATION: { return NodeText { kj::strTree(), kj::strTree(), kj::strTree(), kj::strTree(), kj::strTree(), kj::strTree(), kj::strTree(), }; } } KJ_UNREACHABLE; } // ----------------------------------------------------------------- struct FileText { kj::StringTree header; kj::StringTree source; }; FileText makeFileText(Schema schema, schema::CodeGeneratorRequest::RequestedFile::Reader request) { usedImports.clear(); auto node = schema.getProto(); auto displayName = node.getDisplayName(); kj::Vector> namespaceParts; kj::String namespacePrefix; for (auto annotation: node.getAnnotations()) { if (annotation.getId() == NAMESPACE_ANNOTATION_ID) { kj::StringPtr ns = annotation.getValue().getText(); kj::StringPtr ns2 = ns; namespacePrefix = kj::str("::", ns); for (;;) { KJ_IF_MAYBE(colonPos, ns.findFirst(':')) { namespaceParts.add(ns.slice(0, *colonPos)); ns = ns.slice(*colonPos); if (!ns.startsWith("::")) { context.exitError(kj::str(displayName, ": invalid namespace spec: ", ns2)); } ns = ns.slice(2); } else { namespaceParts.add(ns); break; } } break; } } auto nodeTexts = KJ_MAP(nested, node.getNestedNodes()) { return makeNodeText(namespacePrefix, "", nested.getName(), schemaLoader.getUnbound(nested.getId()), TemplateContext()); }; kj::String separator = kj::str("// ", kj::repeat('=', 87), "\n"); kj::Vector includes; for (auto import: request.getImports()) { if (usedImports.count(import.getId()) > 0) { includes.add(import.getName()); } } kj::StringTree sourceDefs = kj::strTree( KJ_MAP(n, nodeTexts) { return kj::mv(n.sourceFileDefs); }); return FileText { kj::strTree( "// Generated by Cap'n Proto compiler, DO NOT EDIT\n" "// source: ", baseName(displayName), "\n" "\n" "#pragma once\n" "\n" "#include \n" "#include \n", // work-around macro conflict with VOID hasInterfaces ? kj::strTree( "#if !CAPNP_LITE\n" "#include \n" "#endif // !CAPNP_LITE\n" ) : kj::strTree(), "\n" "#ifndef CAPNP_VERSION\n" "#error \"CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?\"\n" "#elif CAPNP_VERSION != ", CAPNP_VERSION, "\n" "#error \"Version mismatch between generated code and library headers. You must " "use the same version of the Cap'n Proto compiler and library.\"\n" "#endif\n" "\n", KJ_MAP(path, includes) { if (path.startsWith("/")) { return kj::strTree("#include <", path.slice(1), ".h>\n"); } else { return kj::strTree("#include \"", path, ".h\"\n"); } }, "\n" "CAPNP_BEGIN_HEADER\n" "\n" "namespace capnp {\n" "namespace schemas {\n" "\n", KJ_MAP(n, nodeTexts) { return kj::mv(n.capnpSchemaDecls); }, "\n" "} // namespace schemas\n" "} // namespace capnp\n" "\n", KJ_MAP(n, namespaceParts) { return kj::strTree("namespace ", n, " {\n"); }, "\n", KJ_MAP(n, nodeTexts) { return kj::mv(n.outerTypeDef); }, separator, "\n", KJ_MAP(n, nodeTexts) { return kj::mv(n.readerBuilderDefs); }, separator, "\n", KJ_MAP(n, nodeTexts) { return kj::mv(n.inlineMethodDefs); }, KJ_MAP(n, namespaceParts) { return kj::strTree("} // namespace\n"); }, "\n" "CAPNP_END_HEADER\n" "\n"), kj::strTree( "// Generated by Cap'n Proto compiler, DO NOT EDIT\n" "// source: ", baseName(displayName), "\n" "\n" "#include \"", baseName(displayName), ".h\"\n" "\n" "namespace capnp {\n" "namespace schemas {\n", KJ_MAP(n, nodeTexts) { return kj::mv(n.capnpSchemaDefs); }, "} // namespace schemas\n" "} // namespace capnp\n", sourceDefs.size() == 0 ? kj::strTree() : kj::strTree( "\n", separator, "\n", KJ_MAP(n, namespaceParts) { return kj::strTree("namespace ", n, " {\n"); }, "\n", kj::mv(sourceDefs), "\n", KJ_MAP(n, namespaceParts) { return kj::strTree("} // namespace\n"); }, "\n")) }; } // ----------------------------------------------------------------- kj::Own fs = kj::newDiskFilesystem(); void writeFile(kj::StringPtr filename, const kj::StringTree& text) { // We don't use replaceFile() here because atomic replacements are actually detrimental for // build tools: // - It's the responsibility of the build pipeline to ensure that no one else is concurrently // reading the file when we write it, so atomicity brings no benefit. // - Atomic replacements force disk syncs which could slow us down for no benefit at all. // - Opening the existing file and overwriting it may allow the filesystem to reuse // already-allocated blocks, or maybe even notice that no actual changes occurred. // - In a power outage scenario, the user would obviously restart the build from scratch // anyway. // // At one point, in a fit of over-engineering, we used writable mmap() here. That turned out // to be a bad idea: writable mmap() is not implemented on some filesystems, especially shared // folders in VirtualBox. Oh well. auto path = kj::Path::parse(filename); auto file = fs->getCurrent().openFile(path, kj::WriteMode::CREATE | kj::WriteMode::MODIFY | kj::WriteMode::CREATE_PARENT); file->writeAll(text.flatten()); } kj::MainBuilder::Validity run() { ReaderOptions options; options.traversalLimitInWords = 1 << 30; // Don't limit. StreamFdMessageReader reader(0, options); auto request = reader.getRoot(); auto capnpVersion = request.getCapnpVersion(); if (capnpVersion.getMajor() != CAPNP_VERSION_MAJOR || capnpVersion.getMinor() != CAPNP_VERSION_MINOR || capnpVersion.getMicro() != CAPNP_VERSION_MICRO) { auto compilerVersion = request.hasCapnpVersion() ? kj::str(capnpVersion.getMajor(), '.', capnpVersion.getMinor(), '.', capnpVersion.getMicro()) : kj::str("pre-0.6"); // pre-0.6 didn't send the version. auto generatorVersion = kj::str( CAPNP_VERSION_MAJOR, '.', CAPNP_VERSION_MINOR, '.', CAPNP_VERSION_MICRO); KJ_LOG(WARNING, "You appear to be using different versions of 'capnp' (the compiler) and " "'capnpc-c++' (the code generator). This can happen, for example, if you built " "a custom version of 'capnp' but then ran it with '-oc++', which invokes " "'capnpc-c++' from your PATH (i.e. the installed version). To specify an alternate " "'capnpc-c++' executable, try something like '-o/path/to/capnpc-c++' instead.", compilerVersion, generatorVersion); } for (auto node: request.getNodes()) { schemaLoader.load(node); } schemaLoader.computeOptimizationHints(); for (auto requestedFile: request.getRequestedFiles()) { auto schema = schemaLoader.get(requestedFile.getId()); auto fileText = makeFileText(schema, requestedFile); writeFile(kj::str(schema.getProto().getDisplayName(), ".h"), fileText.header); writeFile(kj::str(schema.getProto().getDisplayName(), ".c++"), fileText.source); } return true; } }; } // namespace } // namespace capnp KJ_MAIN(capnp::CapnpcCppMain); capnproto-c++-1.1.0/src/capnp/compiler/lexer.h0000644000175000017500000000733614527152321021747 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include "error-reporter.h" CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { bool lex(kj::ArrayPtr input, LexedStatements::Builder result, ErrorReporter& errorReporter); bool lex(kj::ArrayPtr input, LexedTokens::Builder result, ErrorReporter& errorReporter); // Lex the given source code, placing the results in `result`. Returns true if there // were no errors, false if there were. Even when errors are present, the file may have partial // content which can be fed into later stages of parsing in order to find more errors. // // There are two versions, one that parses a list of statements, and one which just parses tokens // that might form a part of one statement. In other words, in the later case, the input should // not contain semicolons or curly braces, unless they are in string literals of course. class Lexer { // Advanced lexer interface. This interface exposes the inner parsers so that you can embed them // into your own parsers. public: Lexer(Orphanage orphanage, ErrorReporter& errorReporter); // `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is // a pointer to the beginning of the input, used to compute byte offsets. ~Lexer() noexcept(false); class ParserInput: public kj::parse::IteratorInput { // Like IteratorInput except that positions are measured as byte offsets // rather than pointers. public: ParserInput(const char* begin, const char* end) : IteratorInput(begin, end), begin(begin) {} explicit ParserInput(ParserInput& parent) : IteratorInput(parent), begin(parent.begin) {} inline uint32_t getBest() { return IteratorInput::getBest() - begin; } inline uint32_t getPosition() { return IteratorInput::getPosition() - begin; } private: const char* begin; }; template using Parser = kj::parse::ParserRef; struct Parsers { Parser> emptySpace; Parser> token; Parser>> tokenSequence; Parser> statement; Parser>> statementSequence; }; const Parsers& getParsers() { return parsers; } private: Orphanage orphanage; kj::Arena arena; Parsers parsers; }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/type-id-test.c++0000644000175000017500000000437414527152321023300 0ustar00kentonkenton00000000000000// Copyright (c) 2017 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "type-id.h" #include #include namespace capnp { namespace compiler { namespace { KJ_TEST("type ID generation hasn't changed") { KJ_EXPECT(generateChildId(0xa93fc509624c72d9ull, "Node") == 0xe682ab4cf923a417ull); KJ_EXPECT(generateChildId(0xe682ab4cf923a417ull, "NestedNode") == 0xdebf55bbfa0fc242ull); KJ_EXPECT(generateGroupId(0xe682ab4cf923a417ull, 7) == 0x9ea0b19b37fb4435ull); KJ_EXPECT(typeId() == 0xe682ab4cf923a417ull); KJ_EXPECT(typeId() == 0xdebf55bbfa0fc242ull); KJ_EXPECT(typeId() == 0x9ea0b19b37fb4435ull); // Methods of TestInterface. KJ_EXPECT(generateMethodParamsId(0x88eb12a0e0af92b2ull, 0, false) == 0xb874edc0d559b391ull); KJ_EXPECT(generateMethodParamsId(0x88eb12a0e0af92b2ull, 0, true) == 0xb04fcaddab714ba4ull); KJ_EXPECT(generateMethodParamsId(0x88eb12a0e0af92b2ull, 1, false) == 0xd044893357b42568ull); KJ_EXPECT(generateMethodParamsId(0x88eb12a0e0af92b2ull, 1, true) == 0x9bf141df4247d52full); } } // namespace } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/node-translator.c++0000644000175000017500000026742314731420004024063 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "node-translator.h" #include "parser.h" // only for generateGroupId() and expressionString() #include #include #include #include #include #include #include #include namespace capnp { namespace compiler { bool shouldDetectIssue344() { return getenv("CAPNP_IGNORE_ISSUE_344") == nullptr; } class NodeTranslator::StructLayout { // Massive, disgusting class which implements the layout algorithm, which decides the offset // for each field. public: template struct HoleSet { inline HoleSet(): holes{0, 0, 0, 0, 0, 0} {} // Represents a set of "holes" within a segment of allocated space, up to one hole of each // power-of-two size between 1 bit and 32 bits. // // The amount of "used" space in a struct's data segment can always be represented as a // combination of a word count and a HoleSet. The HoleSet represents the space lost to // "padding". // // There can never be more than one hole of any particular size. Why is this? Well, consider // that every data field has a power-of-two size, every field must be aligned to a multiple of // its size, and the maximum size of a single field is 64 bits. If we need to add a new field // of N bits, there are two possibilities: // 1. A hole of size N or larger exists. In this case, we find the smallest hole that is at // least N bits. Let's say that that hole has size M. We allocate the first N bits of the // hole to the new field. The remaining M - N bits become a series of holes of sizes N*2, // N*4, ..., M / 2. We know no holes of these sizes existed before because we chose M to be // the smallest available hole larger than N. So, there is still no more than one hole of // each size, and no hole larger than any hole that existed previously. // 2. No hole equal or larger N exists. In that case we extend the data section's size by one // word, creating a new 64-bit hole at the end. We then allocate N bits from it, creating // a series of holes between N and 64 bits, as described in point (1). Thus, again, there // is still at most one hole of each size, and the largest hole is 32 bits. UIntType holes[6]; // The offset of each hole as a multiple of its size. A value of zero indicates that no hole // exists. Notice that it is impossible for any actual hole to have an offset of zero, because // the first field allocated is always placed at the very beginning of the section. So either // the section has a size of zero (in which case there are no holes), or offset zero is // already allocated and therefore cannot be a hole. kj::Maybe tryAllocate(UIntType lgSize) { // Try to find space for a field of size 2^lgSize within the set of holes. If found, // remove it from the holes, and return its offset (as a multiple of its size). If there // is no such space, returns zero (no hole can be at offset zero, as explained above). if (lgSize >= kj::size(holes)) { return nullptr; } else if (holes[lgSize] != 0) { UIntType result = holes[lgSize]; holes[lgSize] = 0; return result; } else { KJ_IF_MAYBE(next, tryAllocate(lgSize + 1)) { UIntType result = *next * 2; holes[lgSize] = result + 1; return result; } else { return nullptr; } } } uint assertHoleAndAllocate(UIntType lgSize) { KJ_ASSERT(holes[lgSize] != 0); uint result = holes[lgSize]; holes[lgSize] = 0; return result; } void addHolesAtEnd(UIntType lgSize, UIntType offset, UIntType limitLgSize = sizeof(HoleSet::holes) / sizeof(HoleSet::holes[0])) { // Add new holes of progressively larger sizes in the range [lgSize, limitLgSize) starting // from the given offset. The idea is that you just allocated an lgSize-sized field from // an limitLgSize-sized space, such as a newly-added word on the end of the data segment. KJ_ASSUME(limitLgSize <= kj::size(holes)); while (lgSize < limitLgSize) { KJ_DREQUIRE(holes[lgSize] == 0); KJ_DREQUIRE(offset % 2 == 1); holes[lgSize] = offset; ++lgSize; offset = (offset + 1) / 2; } } bool tryExpand(UIntType oldLgSize, uint oldOffset, uint expansionFactor) { // Try to expand the value at the given location by combining it with subsequent holes, so // as to expand the location to be 2^expansionFactor times the size that it started as. // (In other words, the new lgSize is oldLgSize + expansionFactor.) if (expansionFactor == 0) { // No expansion requested. return true; } if (oldLgSize == kj::size(holes)) { // Old value is already a full word. Further expansion is impossible. return false; } KJ_ASSERT(oldLgSize < kj::size(holes)); if (holes[oldLgSize] != oldOffset + 1) { // The space immediately after the location is not a hole. return false; } // We can expand the location by one factor by combining it with a hole. Try to further // expand from there to the number of factors requested. if (tryExpand(oldLgSize + 1, oldOffset >> 1, expansionFactor - 1)) { // Success. Consume the hole. holes[oldLgSize] = 0; return true; } else { return false; } } kj::Maybe smallestAtLeast(uint size) { // Return the size of the smallest hole that is equal to or larger than the given size. for (uint i = size; i < kj::size(holes); i++) { if (holes[i] != 0) { return i; } } return nullptr; } uint getFirstWordUsed() { // Computes the lg of the amount of space used in the first word of the section. // If there is a 32-bit hole with a 32-bit offset, no more than the first 32 bits are used. // If no more than the first 32 bits are used, and there is a 16-bit hole with a 16-bit // offset, then no more than the first 16 bits are used. And so on. for (uint i = kj::size(holes); i > 0; i--) { if (holes[i - 1] != 1) { return i; } } return 0; } }; struct StructOrGroup { // Abstract interface for scopes in which fields can be added. virtual void addVoid() = 0; virtual uint addData(uint lgSize) = 0; virtual uint addPointer() = 0; virtual bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) = 0; // Try to expand the given previously-allocated space by 2^expansionFactor. Succeeds -- // returning true -- if the following space happens to be empty, making this expansion possible. // Otherwise, returns false. }; struct Top: public StructOrGroup { uint dataWordCount = 0; uint pointerCount = 0; // Size of the struct so far. HoleSet holes; void addVoid() override {} uint addData(uint lgSize) override { KJ_IF_MAYBE(hole, holes.tryAllocate(lgSize)) { return *hole; } else { uint offset = dataWordCount++ << (6 - lgSize); holes.addHolesAtEnd(lgSize, offset + 1); return offset; } } uint addPointer() override { return pointerCount++; } bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) override { return holes.tryExpand(oldLgSize, oldOffset, expansionFactor); } Top() = default; KJ_DISALLOW_COPY_AND_MOVE(Top); }; struct Union { struct DataLocation { uint lgSize; uint offset; bool tryExpandTo(Union& u, uint newLgSize) { if (newLgSize <= lgSize) { return true; } else if (u.parent.tryExpandData(lgSize, offset, newLgSize - lgSize)) { offset >>= (newLgSize - lgSize); lgSize = newLgSize; return true; } else { return false; } } }; StructOrGroup& parent; uint groupCount = 0; kj::Maybe discriminantOffset; kj::Vector dataLocations; kj::Vector pointerLocations; inline Union(StructOrGroup& parent): parent(parent) {} KJ_DISALLOW_COPY_AND_MOVE(Union); uint addNewDataLocation(uint lgSize) { // Add a whole new data location to the union with the given size. uint offset = parent.addData(lgSize); dataLocations.add(DataLocation { lgSize, offset }); return offset; } uint addNewPointerLocation() { // Add a whole new pointer location to the union with the given size. return pointerLocations.add(parent.addPointer()); } void newGroupAddingFirstMember() { if (++groupCount == 2) { addDiscriminant(); } } bool addDiscriminant() { if (discriminantOffset == nullptr) { discriminantOffset = parent.addData(4); // 2^4 = 16 bits return true; } else { return false; } } }; struct Group final: public StructOrGroup { public: class DataLocationUsage { public: DataLocationUsage(): isUsed(false) {} explicit DataLocationUsage(uint lgSize): isUsed(true), lgSizeUsed(lgSize) {} kj::Maybe smallestHoleAtLeast(Union::DataLocation& location, uint lgSize) { // Find the smallest single hole that is at least the given size. This is used to find the // optimal place to allocate each field -- it is placed in the smallest slot where it fits, // to reduce fragmentation. Returns the size of the hole, if found. if (!isUsed) { // The location is effectively one big hole. if (lgSize <= location.lgSize) { return location.lgSize; } else { return nullptr; } } else if (lgSize >= lgSizeUsed) { // Requested size is at least our current usage, so clearly won't fit in any current // holes, but if the location's size is larger than what we're using, we'd be able to // expand. if (lgSize < location.lgSize) { return lgSize; } else { return nullptr; } } else KJ_IF_MAYBE(result, holes.smallestAtLeast(lgSize)) { // There's a hole. return *result; } else { // The requested size is smaller than what we're already using, but there are no holes // available. If we could double our size, then we could allocate in the new space. if (lgSizeUsed < location.lgSize) { // We effectively create a new hole the same size as the current usage. return lgSizeUsed; } else { return nullptr; } } } uint allocateFromHole(Group& group, Union::DataLocation& location, uint lgSize) { // Allocate the given space from an existing hole, given smallestHoleAtLeast() already // returned non-null indicating such a hole exists. uint result; if (!isUsed) { // The location is totally unused, so just allocate from the beginning. KJ_DASSERT(lgSize <= location.lgSize, "Did smallestHoleAtLeast() really find a hole?"); result = 0; isUsed = true; lgSizeUsed = lgSize; } else if (lgSize >= lgSizeUsed) { // Requested size is at least our current usage, so clearly won't fit in any holes. // We must expand to double the requested size, and return the second half. KJ_DASSERT(lgSize < location.lgSize, "Did smallestHoleAtLeast() really find a hole?"); holes.addHolesAtEnd(lgSizeUsed, 1, lgSize); lgSizeUsed = lgSize + 1; result = 1; } else KJ_IF_MAYBE(hole, holes.tryAllocate(lgSize)) { // Found a hole. result = *hole; } else { // The requested size is smaller than what we're using so far, but didn't fit in a // hole. We should double our "used" size, then allocate from the new space. KJ_DASSERT(lgSizeUsed < location.lgSize, "Did smallestHoleAtLeast() really find a hole?"); result = 1 << (lgSizeUsed - lgSize); holes.addHolesAtEnd(lgSize, result + 1, lgSizeUsed); lgSizeUsed += 1; } // Adjust the offset according to the location's offset before returning. uint locationOffset = location.offset << (location.lgSize - lgSize); return locationOffset + result; } kj::Maybe tryAllocateByExpanding( Group& group, Union::DataLocation& location, uint lgSize) { // Attempt to allocate the given size by requesting that the parent union expand this // location to fit. This is used if smallestHoleAtLeast() already determined that there // are no holes that would fit, so we don't bother checking that. if (!isUsed) { if (location.tryExpandTo(group.parent, lgSize)) { isUsed = true; lgSizeUsed = lgSize; return location.offset << (location.lgSize - lgSize); } else { return nullptr; } } else { uint newSize = kj::max(lgSizeUsed, lgSize) + 1; if (tryExpandUsage(group, location, newSize, true)) { uint result = KJ_ASSERT_NONNULL(holes.tryAllocate(lgSize)); uint locationOffset = location.offset << (location.lgSize - lgSize); return locationOffset + result; } else { return nullptr; } } } bool tryExpand(Group& group, Union::DataLocation& location, uint oldLgSize, uint oldOffset, uint expansionFactor) { if (oldOffset == 0 && lgSizeUsed == oldLgSize) { // This location contains exactly the requested data, so just expand the whole thing. return tryExpandUsage(group, location, oldLgSize + expansionFactor, false); } else { // This location contains the requested data plus other stuff. Therefore the data cannot // possibly expand past the end of the space we've already marked used without either // overlapping with something else or breaking alignment rules. We only have to combine // it with holes. return holes.tryExpand(oldLgSize, oldOffset, expansionFactor); } } private: bool isUsed; // Whether or not this location has been used at all by the group. uint8_t lgSizeUsed; // Amount of space from the location which is "used". This is the minimum size needed to // cover all allocated space. Only meaningful if `isUsed` is true. HoleSet holes; // Indicates holes present in the space designated by `lgSizeUsed`. The offsets in this // HoleSet are relative to the beginning of this particular data location, not the beginning // of the struct. bool tryExpandUsage(Group& group, Union::DataLocation& location, uint desiredUsage, bool newHoles) { if (desiredUsage > location.lgSize) { // Need to expand the underlying slot. if (!location.tryExpandTo(group.parent, desiredUsage)) { return false; } } // Underlying slot is big enough, so expand our size and update holes. if (newHoles) { holes.addHolesAtEnd(lgSizeUsed, 1, desiredUsage); } else if (shouldDetectIssue344()) { // Unfortunately, Cap'n Proto 0.5.x and below would always call addHolesAtEnd(), which // was the wrong thing to do when called from tryExpand(), which itself is only called // in cases involving unions nested in other unions. The bug could lead to multiple // fields in a group incorrectly being assigned overlapping offsets. Although the bug // is now fixed by adding the `newHoles` parameter, this silently breaks // backwards-compatibility with affected schemas. Therefore, for now, we throw an // exception to alert developers of the problem. // // TODO(cleanup): Once sufficient time has elapsed, remove this assert. KJ_FAIL_ASSERT("Bad news: Cap'n Proto 0.5.x and previous contained a bug which would cause this schema to be compiled incorrectly. Please see: https://github.com/capnproto/capnproto/issues/344"); } lgSizeUsed = desiredUsage; return true; } }; Union& parent; kj::Vector parentDataLocationUsage; // Vector corresponding to the parent union's `dataLocations`, indicating how much of each // location has already been allocated. uint parentPointerLocationUsage = 0; // Number of parent's pointer locations that have been used by this group. bool hasMembers = false; inline Group(Union& parent): parent(parent) {} KJ_DISALLOW_COPY_AND_MOVE(Group); void addMember() { if (!hasMembers) { hasMembers = true; parent.newGroupAddingFirstMember(); } } void addVoid() override { addMember(); // Make sure that if this is a member of a union which is in turn a member of another union, // that we let the outer union know that a field is being added, even though it is a // zero-size field. This is important because the union needs to allocate its discriminant // just before its second member is added. parent.parent.addVoid(); } uint addData(uint lgSize) override { addMember(); uint bestSize = kj::maxValue; kj::Maybe bestLocation = nullptr; for (uint i = 0; i < parent.dataLocations.size(); i++) { // If we haven't seen this DataLocation yet, add a corresponding DataLocationUsage. if (parentDataLocationUsage.size() == i) { parentDataLocationUsage.add(); } auto& usage = parentDataLocationUsage[i]; KJ_IF_MAYBE(hole, usage.smallestHoleAtLeast(parent.dataLocations[i], lgSize)) { if (*hole < bestSize) { bestSize = *hole; bestLocation = i; } } } KJ_IF_MAYBE(best, bestLocation) { return parentDataLocationUsage[*best].allocateFromHole( *this, parent.dataLocations[*best], lgSize); } // There are no holes at all in the union big enough to fit this field. Go back through all // of the locations and attempt to expand them to fit. for (uint i = 0; i < parent.dataLocations.size(); i++) { KJ_IF_MAYBE(result, parentDataLocationUsage[i].tryAllocateByExpanding( *this, parent.dataLocations[i], lgSize)) { return *result; } } // Couldn't find any space in the existing locations, so add a new one. uint result = parent.addNewDataLocation(lgSize); parentDataLocationUsage.add(lgSize); return result; } uint addPointer() override { addMember(); if (parentPointerLocationUsage < parent.pointerLocations.size()) { return parent.pointerLocations[parentPointerLocationUsage++]; } else { parentPointerLocationUsage++; return parent.addNewPointerLocation(); } } bool tryExpandData(uint oldLgSize, uint oldOffset, uint expansionFactor) override { bool mustFail = false; if (oldLgSize + expansionFactor > 6 || (oldOffset & ((1 << expansionFactor) - 1)) != 0) { // Expansion is not possible because the new size is too large or the offset is not // properly-aligned. // Unfortunately, Cap'n Proto 0.5.x and prior forgot to "return false" here, instead // continuing to execute the rest of the method. In most cases, the method failed later // on, causing no harm. But, in cases where the method later succeeded, it probably // led to bogus layouts. We cannot simply add the return statement now as this would // silently break backwards-compatibility with affected schemas. Instead, we detect the // problem and throw an exception. // // TODO(cleanup): Once sufficient time has elapsed, switch to "return false;" here. if (shouldDetectIssue344()) { mustFail = true; } else { return false; } } for (uint i = 0; i < parentDataLocationUsage.size(); i++) { auto& location = parent.dataLocations[i]; if (location.lgSize >= oldLgSize && oldOffset >> (location.lgSize - oldLgSize) == location.offset) { // The location we're trying to expand is a subset of this data location. auto& usage = parentDataLocationUsage[i]; // Adjust the offset to be only within this location. uint localOldOffset = oldOffset - (location.offset << (location.lgSize - oldLgSize)); // Try to expand. bool result = usage.tryExpand( *this, location, oldLgSize, localOldOffset, expansionFactor); if (mustFail && result) { KJ_FAIL_ASSERT("Bad news: Cap'n Proto 0.5.x and previous contained a bug which would cause this schema to be compiled incorrectly. Please see: https://github.com/capnproto/capnproto/issues/344"); } return result; } } KJ_FAIL_ASSERT("Tried to expand field that was never allocated."); return false; } }; Top& getTop() { return top; } private: Top top; }; // ======================================================================================= NodeTranslator::NodeTranslator( Resolver& resolver, ErrorReporter& errorReporter, const Declaration::Reader& decl, Orphan wipNodeParam, bool compileAnnotations) : resolver(resolver), errorReporter(errorReporter), orphanage(Orphanage::getForMessageContaining(wipNodeParam.get())), compileAnnotations(compileAnnotations), localBrand(kj::refcounted( errorReporter, wipNodeParam.getReader().getId(), decl.getParameters().size(), resolver)), wipNode(kj::mv(wipNodeParam)), sourceInfo(orphanage.newOrphan()) { compileNode(decl, wipNode.get()); } NodeTranslator::~NodeTranslator() noexcept(false) {} NodeTranslator::NodeSet NodeTranslator::getBootstrapNode() { auto sourceInfos = kj::heapArrayBuilder( 1 + groups.size() + paramStructs.size()); sourceInfos.add(sourceInfo.getReader()); for (auto& group: groups) { sourceInfos.add(group.sourceInfo.getReader()); } for (auto& paramStruct: paramStructs) { sourceInfos.add(paramStruct.sourceInfo.getReader()); } auto nodeReader = wipNode.getReader(); if (nodeReader.isInterface()) { return NodeSet { nodeReader, KJ_MAP(g, paramStructs) { return g.node.getReader(); }, sourceInfos.finish() }; } else { return NodeSet { nodeReader, KJ_MAP(g, groups) { return g.node.getReader(); }, sourceInfos.finish() }; } } NodeTranslator::NodeSet NodeTranslator::finish(Schema selfBootstrapSchema) { // Careful about iteration here: compileFinalValue() may actually add more elements to // `unfinishedValues`, invalidating iterators in the process. for (size_t i = 0; i < unfinishedValues.size(); i++) { auto& value = unfinishedValues[i]; compileValue(value.source, value.type, value.typeScope.orDefault(selfBootstrapSchema), value.target, false); } return getBootstrapNode(); } class NodeTranslator::DuplicateNameDetector { public: inline explicit DuplicateNameDetector(ErrorReporter& errorReporter) : errorReporter(errorReporter) {} void check(List::Reader nestedDecls, Declaration::Which parentKind); private: ErrorReporter& errorReporter; std::map names; }; void NodeTranslator::compileNode(Declaration::Reader decl, schema::Node::Builder builder) { DuplicateNameDetector(errorReporter) .check(decl.getNestedDecls(), decl.which()); auto genericParams = decl.getParameters(); if (genericParams.size() > 0) { auto paramsBuilder = builder.initParameters(genericParams.size()); for (auto i: kj::indices(genericParams)) { paramsBuilder[i].setName(genericParams[i].getName()); } } builder.setIsGeneric(localBrand->isGeneric()); kj::StringPtr targetsFlagName; switch (decl.which()) { case Declaration::FILE: targetsFlagName = "targetsFile"; break; case Declaration::CONST: compileConst(decl.getConst(), builder.initConst()); targetsFlagName = "targetsConst"; break; case Declaration::ANNOTATION: compileAnnotation(decl.getAnnotation(), builder.initAnnotation()); targetsFlagName = "targetsAnnotation"; break; case Declaration::ENUM: compileEnum(decl.getEnum(), decl.getNestedDecls(), builder); targetsFlagName = "targetsEnum"; break; case Declaration::STRUCT: compileStruct(decl.getStruct(), decl.getNestedDecls(), builder); targetsFlagName = "targetsStruct"; break; case Declaration::INTERFACE: compileInterface(decl.getInterface(), decl.getNestedDecls(), builder); targetsFlagName = "targetsInterface"; break; default: KJ_FAIL_REQUIRE("This Declaration is not a node."); break; } if (decl.which() != Declaration::ANNOTATION) { builder.setStartByte(decl.getStartByte()); builder.setEndByte(decl.getEndByte()); } builder.adoptAnnotations(compileAnnotationApplications(decl.getAnnotations(), targetsFlagName)); auto di = sourceInfo.get(); di.setId(wipNode.getReader().getId()); if (decl.hasDocComment()) { di.setDocComment(decl.getDocComment()); } di.setStartByte(decl.getStartByte()); di.setEndByte(decl.getEndByte()); } static kj::StringPtr getExpressionTargetName(Expression::Reader exp) { switch (exp.which()) { case Expression::ABSOLUTE_NAME: return exp.getAbsoluteName().getValue(); case Expression::RELATIVE_NAME: return exp.getRelativeName().getValue(); case Expression::APPLICATION: return getExpressionTargetName(exp.getApplication().getFunction()); case Expression::MEMBER: return exp.getMember().getName().getValue(); default: return nullptr; } } void NodeTranslator::DuplicateNameDetector::check( List::Reader nestedDecls, Declaration::Which parentKind) { for (auto decl: nestedDecls) { { auto name = decl.getName(); auto nameText = name.getValue(); auto insertResult = names.insert(std::make_pair(nameText, name)); if (!insertResult.second) { if (nameText.size() == 0 && decl.isUnion()) { errorReporter.addErrorOn( name, kj::str("An unnamed union is already defined in this scope.")); errorReporter.addErrorOn( insertResult.first->second, kj::str("Previously defined here.")); } else { errorReporter.addErrorOn( name, kj::str("'", nameText, "' is already defined in this scope.")); errorReporter.addErrorOn( insertResult.first->second, kj::str("'", nameText, "' previously defined here.")); } } switch (decl.which()) { case Declaration::USING: { kj::StringPtr targetName = getExpressionTargetName(decl.getUsing().getTarget()); if (targetName.size() > 0 && targetName[0] >= 'a' && targetName[0] <= 'z') { // Target starts with lower-case letter, so alias should too. if (nameText.size() > 0 && (nameText[0] < 'a' || nameText[0] > 'z')) { errorReporter.addErrorOn(name, "Non-type names must begin with a lower-case letter."); } } else { // Target starts with capital or is not named (probably, an import). Require // capitalization. if (nameText.size() > 0 && (nameText[0] < 'A' || nameText[0] > 'Z')) { errorReporter.addErrorOn(name, "Type names must begin with a capital letter."); } } break; } case Declaration::ENUM: case Declaration::STRUCT: case Declaration::INTERFACE: if (nameText.size() > 0 && (nameText[0] < 'A' || nameText[0] > 'Z')) { errorReporter.addErrorOn(name, "Type names must begin with a capital letter."); } break; case Declaration::CONST: case Declaration::ANNOTATION: case Declaration::ENUMERANT: case Declaration::METHOD: case Declaration::FIELD: case Declaration::UNION: case Declaration::GROUP: if (nameText.size() > 0 && (nameText[0] < 'a' || nameText[0] > 'z')) { errorReporter.addErrorOn(name, "Non-type names must begin with a lower-case letter."); } break; default: KJ_ASSERT(nameText.size() == 0, "Don't know what naming rules to enforce for node type.", (uint)decl.which()); break; } if (nameText.findFirst('_') != nullptr) { errorReporter.addErrorOn(name, "Cap'n Proto declaration names should use camelCase and must not contain " "underscores. (Code generators may convert names to the appropriate style for the " "target language.)"); } } switch (decl.which()) { case Declaration::USING: case Declaration::CONST: case Declaration::ENUM: case Declaration::STRUCT: case Declaration::INTERFACE: case Declaration::ANNOTATION: switch (parentKind) { case Declaration::FILE: case Declaration::STRUCT: case Declaration::INTERFACE: // OK. break; default: errorReporter.addErrorOn(decl, "This kind of declaration doesn't belong here."); break; } break; case Declaration::ENUMERANT: if (parentKind != Declaration::ENUM) { errorReporter.addErrorOn(decl, "Enumerants can only appear in enums."); } break; case Declaration::METHOD: if (parentKind != Declaration::INTERFACE) { errorReporter.addErrorOn(decl, "Methods can only appear in interfaces."); } break; case Declaration::FIELD: case Declaration::UNION: case Declaration::GROUP: switch (parentKind) { case Declaration::STRUCT: case Declaration::UNION: case Declaration::GROUP: // OK. break; default: errorReporter.addErrorOn(decl, "This declaration can only appear in structs."); break; } // Struct members may have nested decls. We need to check those here, because no one else // is going to do it. if (decl.getName().getValue().size() == 0) { // Unnamed union. Check members as if they are in the same scope. check(decl.getNestedDecls(), decl.which()); } else { // Children are in their own scope. DuplicateNameDetector(errorReporter) .check(decl.getNestedDecls(), decl.which()); } break; default: errorReporter.addErrorOn(decl, "This kind of declaration doesn't belong here."); break; } } } void NodeTranslator::compileConst(Declaration::Const::Reader decl, schema::Node::Const::Builder builder) { auto typeBuilder = builder.initType(); if (compileType(decl.getType(), typeBuilder, ImplicitParams::none())) { compileBootstrapValue(decl.getValue(), typeBuilder.asReader(), builder.initValue()); } } void NodeTranslator::compileAnnotation(Declaration::Annotation::Reader decl, schema::Node::Annotation::Builder builder) { compileType(decl.getType(), builder.initType(), ImplicitParams::none()); // Dynamically copy over the values of all of the "targets" members. DynamicStruct::Reader src = decl; DynamicStruct::Builder dst = builder; for (auto srcField: src.getSchema().getFields()) { kj::StringPtr fieldName = srcField.getProto().getName(); if (fieldName.startsWith("targets")) { auto dstField = dst.getSchema().getFieldByName(fieldName); dst.set(dstField, src.get(srcField)); } } } class NodeTranslator::DuplicateOrdinalDetector { public: DuplicateOrdinalDetector(ErrorReporter& errorReporter): errorReporter(errorReporter) {} void check(LocatedInteger::Reader ordinal) { if (ordinal.getValue() < expectedOrdinal) { errorReporter.addErrorOn(ordinal, "Duplicate ordinal number."); KJ_IF_MAYBE(last, lastOrdinalLocation) { errorReporter.addErrorOn( *last, kj::str("Ordinal @", last->getValue(), " originally used here.")); // Don't report original again. lastOrdinalLocation = nullptr; } } else if (ordinal.getValue() > expectedOrdinal) { errorReporter.addErrorOn(ordinal, kj::str("Skipped ordinal @", expectedOrdinal, ". Ordinals must be sequential with no " "holes.")); expectedOrdinal = ordinal.getValue() + 1; } else { ++expectedOrdinal; lastOrdinalLocation = ordinal; } } private: ErrorReporter& errorReporter; uint expectedOrdinal = 0; kj::Maybe lastOrdinalLocation; }; void NodeTranslator::compileEnum(Void decl, List::Reader members, schema::Node::Builder builder) { // maps ordinal -> (code order, declaration) std::multimap> enumerants; uint codeOrder = 0; for (auto member: members) { if (member.isEnumerant()) { enumerants.insert( std::make_pair(member.getId().getOrdinal().getValue(), std::make_pair(codeOrder++, member))); } } auto list = builder.initEnum().initEnumerants(enumerants.size()); auto sourceInfoList = sourceInfo.get().initMembers(enumerants.size()); uint i = 0; DuplicateOrdinalDetector dupDetector(errorReporter); for (auto& entry: enumerants) { uint codeOrder = entry.second.first; Declaration::Reader enumerantDecl = entry.second.second; dupDetector.check(enumerantDecl.getId().getOrdinal()); if (enumerantDecl.hasDocComment()) { sourceInfoList[i].setDocComment(enumerantDecl.getDocComment()); } auto enumerantBuilder = list[i++]; enumerantBuilder.setName(enumerantDecl.getName().getValue()); enumerantBuilder.setCodeOrder(codeOrder); enumerantBuilder.adoptAnnotations(compileAnnotationApplications( enumerantDecl.getAnnotations(), "targetsEnumerant")); } } // ------------------------------------------------------------------- class NodeTranslator::StructTranslator { public: explicit StructTranslator(NodeTranslator& translator, ImplicitParams implicitMethodParams) : translator(translator), errorReporter(translator.errorReporter), implicitMethodParams(implicitMethodParams) {} KJ_DISALLOW_COPY_AND_MOVE(StructTranslator); void translate(Void decl, List::Reader members, schema::Node::Builder builder, schema::Node::SourceInfo::Builder sourceInfo) { // Build the member-info-by-ordinal map. MemberInfo root(builder, sourceInfo); traverseTopOrGroup(members, root, layout.getTop()); translateInternal(root, builder); } void translate(List::Reader params, schema::Node::Builder builder, schema::Node::SourceInfo::Builder sourceInfo) { // Build a struct from a method param / result list. MemberInfo root(builder, sourceInfo); traverseParams(params, root, layout.getTop()); translateInternal(root, builder); } private: NodeTranslator& translator; ErrorReporter& errorReporter; ImplicitParams implicitMethodParams; StructLayout layout; kj::Arena arena; struct NodeSourceInfoBuilderPair { schema::Node::Builder node; schema::Node::SourceInfo::Builder sourceInfo; }; struct FieldSourceInfoBuilderPair { schema::Field::Builder field; schema::Node::SourceInfo::Member::Builder sourceInfo; }; struct MemberInfo { MemberInfo* parent; // The MemberInfo for the parent scope. uint codeOrder; // Code order within the parent. uint index = 0; // Index within the parent. uint childCount = 0; // Number of children this member has. uint childInitializedCount = 0; // Number of children whose `schema` member has been initialized. This initialization happens // while walking the fields in ordinal order. uint unionDiscriminantCount = 0; // Number of children who are members of the scope's union and have had their discriminant // value decided. bool isInUnion; // Whether or not this field is in the parent's union. kj::StringPtr name; Declaration::Id::Reader declId; Declaration::Which declKind; bool isParam = false; bool hasDefaultValue = false; // if declKind == FIELD Expression::Reader fieldType; // if declKind == FIELD Expression::Reader fieldDefaultValue; // if declKind == FIELD && hasDefaultValue List::Reader declAnnotations; uint startByte = 0; uint endByte = 0; // Information about the field declaration. We don't use Declaration::Reader because it might // have come from a Declaration::Param instead. kj::Maybe docComment = nullptr; kj::Maybe schema; // Schema for the field. Initialized when getSchema() is first called. schema::Node::Builder node; schema::Node::SourceInfo::Builder sourceInfo; // If it's a group, or the top-level struct. union { StructLayout::StructOrGroup* fieldScope; // If this member is a field, the scope of that field. This will be used to assign an // offset for the field when going through in ordinal order. StructLayout::Union* unionScope; // If this member is a union, or it is a group or top-level struct containing an unnamed // union, this is the union. This will be used to assign a discriminant offset when the // union's ordinal comes up (if the union has an explicit ordinal), as well as to finally // copy over the discriminant offset to the schema. }; inline explicit MemberInfo(schema::Node::Builder node, schema::Node::SourceInfo::Builder sourceInfo) : parent(nullptr), codeOrder(0), isInUnion(false), node(node), sourceInfo(sourceInfo), unionScope(nullptr) {} inline MemberInfo(MemberInfo& parent, uint codeOrder, const Declaration::Reader& decl, StructLayout::StructOrGroup& fieldScope, bool isInUnion) : parent(&parent), codeOrder(codeOrder), isInUnion(isInUnion), name(decl.getName().getValue()), declId(decl.getId()), declKind(Declaration::FIELD), declAnnotations(decl.getAnnotations()), startByte(decl.getStartByte()), endByte(decl.getEndByte()), node(nullptr), sourceInfo(nullptr), fieldScope(&fieldScope) { KJ_REQUIRE(decl.which() == Declaration::FIELD); auto fieldDecl = decl.getField(); fieldType = fieldDecl.getType(); if (fieldDecl.getDefaultValue().isValue()) { hasDefaultValue = true; fieldDefaultValue = fieldDecl.getDefaultValue().getValue(); } if (decl.hasDocComment()) { docComment = decl.getDocComment(); } } inline MemberInfo(MemberInfo& parent, uint codeOrder, const Declaration::Param::Reader& decl, StructLayout::StructOrGroup& fieldScope, bool isInUnion) : parent(&parent), codeOrder(codeOrder), isInUnion(isInUnion), name(decl.getName().getValue()), declKind(Declaration::FIELD), isParam(true), declAnnotations(decl.getAnnotations()), startByte(decl.getStartByte()), endByte(decl.getEndByte()), node(nullptr), sourceInfo(nullptr), fieldScope(&fieldScope) { fieldType = decl.getType(); if (decl.getDefaultValue().isValue()) { hasDefaultValue = true; fieldDefaultValue = decl.getDefaultValue().getValue(); } } inline MemberInfo(MemberInfo& parent, uint codeOrder, const Declaration::Reader& decl, NodeSourceInfoBuilderPair builderPair, bool isInUnion) : parent(&parent), codeOrder(codeOrder), isInUnion(isInUnion), name(decl.getName().getValue()), declId(decl.getId()), declKind(decl.which()), declAnnotations(decl.getAnnotations()), startByte(decl.getStartByte()), endByte(decl.getEndByte()), node(builderPair.node), sourceInfo(builderPair.sourceInfo), unionScope(nullptr) { KJ_REQUIRE(decl.which() != Declaration::FIELD); if (decl.hasDocComment()) { docComment = decl.getDocComment(); } } schema::Field::Builder getSchema() { KJ_IF_MAYBE(result, schema) { return *result; } else { index = parent->childInitializedCount; auto builderPair = parent->addMemberSchema(); auto builder = builderPair.field; if (isInUnion) { builder.setDiscriminantValue(parent->unionDiscriminantCount++); } builder.setName(name); builder.setCodeOrder(codeOrder); KJ_IF_MAYBE(dc, docComment) { builderPair.sourceInfo.setDocComment(*dc); } schema = builder; return builder; } } FieldSourceInfoBuilderPair addMemberSchema() { // Get the schema builder for the child member at the given index. This lazily/dynamically // builds the builder tree. KJ_REQUIRE(childInitializedCount < childCount); auto structNode = node.getStruct(); if (!structNode.hasFields()) { if (parent != nullptr) { getSchema(); // Make sure field exists in parent once the first child is added. } FieldSourceInfoBuilderPair result { structNode.initFields(childCount)[childInitializedCount], sourceInfo.initMembers(childCount)[childInitializedCount] }; ++childInitializedCount; return result; } else { FieldSourceInfoBuilderPair result { structNode.getFields()[childInitializedCount], sourceInfo.getMembers()[childInitializedCount] }; ++childInitializedCount; return result; } } void finishGroup() { if (unionScope != nullptr) { unionScope->addDiscriminant(); // if it hasn't happened already auto structNode = node.getStruct(); structNode.setDiscriminantCount(unionDiscriminantCount); structNode.setDiscriminantOffset(KJ_ASSERT_NONNULL(unionScope->discriminantOffset)); } if (parent != nullptr) { uint64_t groupId = generateGroupId(parent->node.getId(), index); node.setId(groupId); node.setScopeId(parent->node.getId()); getSchema().initGroup().setTypeId(groupId); sourceInfo.setId(groupId); KJ_IF_MAYBE(dc, docComment) { sourceInfo.setDocComment(*dc); } } } }; std::multimap membersByOrdinal; // Every member that has an explicit ordinal goes into this map. We then iterate over the map // to assign field offsets (or discriminant offsets for unions). kj::Vector allMembers; // All members, including ones that don't have ordinals. void traverseUnion(const Declaration::Reader& decl, List::Reader members, MemberInfo& parent, StructLayout::Union& layout, uint& codeOrder) { if (members.size() < 2) { errorReporter.addErrorOn(decl, "Union must have at least two members."); } for (auto member: members) { kj::Maybe ordinal; MemberInfo* memberInfo = nullptr; switch (member.which()) { case Declaration::FIELD: { parent.childCount++; // For layout purposes, pretend this field is enclosed in a one-member group. StructLayout::Group& singletonGroup = arena.allocate(layout); memberInfo = &arena.allocate(parent, codeOrder++, member, singletonGroup, true); allMembers.add(memberInfo); ordinal = member.getId().getOrdinal().getValue(); break; } case Declaration::UNION: if (member.getName().getValue() == "") { errorReporter.addErrorOn(member, "Unions cannot contain unnamed unions."); } else { parent.childCount++; // For layout purposes, pretend this union is enclosed in a one-member group. StructLayout::Group& singletonGroup = arena.allocate(layout); StructLayout::Union& unionLayout = arena.allocate(singletonGroup); memberInfo = &arena.allocate( parent, codeOrder++, member, newGroupNode(parent.node, member.getName().getValue()), true); allMembers.add(memberInfo); memberInfo->unionScope = &unionLayout; uint subCodeOrder = 0; traverseUnion(member, member.getNestedDecls(), *memberInfo, unionLayout, subCodeOrder); if (member.getId().isOrdinal()) { ordinal = member.getId().getOrdinal().getValue(); } } break; case Declaration::GROUP: { parent.childCount++; StructLayout::Group& group = arena.allocate(layout); memberInfo = &arena.allocate( parent, codeOrder++, member, newGroupNode(parent.node, member.getName().getValue()), true); allMembers.add(memberInfo); traverseGroup(member.getNestedDecls(), *memberInfo, group); break; } default: // Ignore others. break; } KJ_IF_MAYBE(o, ordinal) { membersByOrdinal.insert(std::make_pair(*o, memberInfo)); } } } void traverseGroup(List::Reader members, MemberInfo& parent, StructLayout::StructOrGroup& layout) { if (members.size() < 1) { errorReporter.addError(parent.startByte, parent.endByte, "Group must have at least one member."); } traverseTopOrGroup(members, parent, layout); } void traverseTopOrGroup(List::Reader members, MemberInfo& parent, StructLayout::StructOrGroup& layout) { uint codeOrder = 0; for (auto member: members) { kj::Maybe ordinal; MemberInfo* memberInfo = nullptr; switch (member.which()) { case Declaration::FIELD: { parent.childCount++; memberInfo = &arena.allocate( parent, codeOrder++, member, layout, false); allMembers.add(memberInfo); ordinal = member.getId().getOrdinal().getValue(); break; } case Declaration::UNION: { StructLayout::Union& unionLayout = arena.allocate(layout); uint independentSubCodeOrder = 0; uint* subCodeOrder = &independentSubCodeOrder; if (member.getName().getValue() == "") { memberInfo = &parent; subCodeOrder = &codeOrder; } else { parent.childCount++; memberInfo = &arena.allocate( parent, codeOrder++, member, newGroupNode(parent.node, member.getName().getValue()), false); allMembers.add(memberInfo); } memberInfo->unionScope = &unionLayout; traverseUnion(member, member.getNestedDecls(), *memberInfo, unionLayout, *subCodeOrder); if (member.getId().isOrdinal()) { ordinal = member.getId().getOrdinal().getValue(); } break; } case Declaration::GROUP: parent.childCount++; memberInfo = &arena.allocate( parent, codeOrder++, member, newGroupNode(parent.node, member.getName().getValue()), false); allMembers.add(memberInfo); // Members of the group are laid out just like they were members of the parent, so we // just pass along the parent layout. traverseGroup(member.getNestedDecls(), *memberInfo, layout); // No ordinal for groups. break; default: // Ignore others. break; } KJ_IF_MAYBE(o, ordinal) { membersByOrdinal.insert(std::make_pair(*o, memberInfo)); } } } void traverseParams(List::Reader params, MemberInfo& parent, StructLayout::StructOrGroup& layout) { for (uint i: kj::indices(params)) { auto param = params[i]; parent.childCount++; MemberInfo* memberInfo = &arena.allocate(parent, i, param, layout, false); allMembers.add(memberInfo); membersByOrdinal.insert(std::make_pair(i, memberInfo)); } } NodeSourceInfoBuilderPair newGroupNode(schema::Node::Reader parent, kj::StringPtr name) { AuxNode aux { translator.orphanage.newOrphan(), translator.orphanage.newOrphan() }; auto node = aux.node.get(); auto sourceInfo = aux.sourceInfo.get(); // We'll set the ID and scope ID later. node.setDisplayName(kj::str(parent.getDisplayName(), '.', name)); node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size()); node.setIsGeneric(parent.getIsGeneric()); node.initStruct().setIsGroup(true); // The remaining contents of node.struct will be filled in later. translator.groups.add(kj::mv(aux)); return { node, sourceInfo }; } void translateInternal(MemberInfo& root, schema::Node::Builder builder) { auto structBuilder = builder.initStruct(); // Go through each member in ordinal order, building each member schema. DuplicateOrdinalDetector dupDetector(errorReporter); for (auto& entry: membersByOrdinal) { MemberInfo& member = *entry.second; // Make sure the exceptions added relating to // https://github.com/capnproto/capnproto/issues/344 identify the affected field. KJ_CONTEXT(member.name); if (member.declId.isOrdinal()) { dupDetector.check(member.declId.getOrdinal()); } schema::Field::Builder fieldBuilder = member.getSchema(); fieldBuilder.getOrdinal().setExplicit(entry.first); switch (member.declKind) { case Declaration::FIELD: { auto slot = fieldBuilder.initSlot(); auto typeBuilder = slot.initType(); if (translator.compileType(member.fieldType, typeBuilder, implicitMethodParams)) { if (member.hasDefaultValue) { if (member.isParam && member.fieldDefaultValue.isRelativeName() && member.fieldDefaultValue.getRelativeName().getValue() == "null") { // special case: parameter set null switch (typeBuilder.which()) { case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: break; default: errorReporter.addErrorOn(member.fieldDefaultValue.getRelativeName(), "Only pointer parameters can declare their default as 'null'."); break; } translator.compileDefaultDefaultValue(typeBuilder, slot.initDefaultValue()); } else { translator.compileBootstrapValue(member.fieldDefaultValue, typeBuilder, slot.initDefaultValue()); } slot.setHadExplicitDefault(true); } else { translator.compileDefaultDefaultValue(typeBuilder, slot.initDefaultValue()); } } else { translator.compileDefaultDefaultValue(typeBuilder, slot.initDefaultValue()); } int lgSize = -1; switch (typeBuilder.which()) { case schema::Type::VOID: lgSize = -1; break; case schema::Type::BOOL: lgSize = 0; break; case schema::Type::INT8: lgSize = 3; break; case schema::Type::INT16: lgSize = 4; break; case schema::Type::INT32: lgSize = 5; break; case schema::Type::INT64: lgSize = 6; break; case schema::Type::UINT8: lgSize = 3; break; case schema::Type::UINT16: lgSize = 4; break; case schema::Type::UINT32: lgSize = 5; break; case schema::Type::UINT64: lgSize = 6; break; case schema::Type::FLOAT32: lgSize = 5; break; case schema::Type::FLOAT64: lgSize = 6; break; case schema::Type::TEXT: lgSize = -2; break; case schema::Type::DATA: lgSize = -2; break; case schema::Type::LIST: lgSize = -2; break; case schema::Type::ENUM: lgSize = 4; break; case schema::Type::STRUCT: lgSize = -2; break; case schema::Type::INTERFACE: lgSize = -2; break; case schema::Type::ANY_POINTER: lgSize = -2; break; } if (lgSize == -2) { // pointer slot.setOffset(member.fieldScope->addPointer()); } else if (lgSize == -1) { // void member.fieldScope->addVoid(); slot.setOffset(0); } else { slot.setOffset(member.fieldScope->addData(lgSize)); } break; } case Declaration::UNION: if (!member.unionScope->addDiscriminant()) { errorReporter.addErrorOn(member.declId.getOrdinal(), "Union ordinal, if specified, must be greater than no more than one of its " "member ordinals (i.e. there can only be one field retroactively unionized)."); } break; case Declaration::GROUP: KJ_FAIL_ASSERT("Groups don't have ordinals."); break; default: KJ_FAIL_ASSERT("Unexpected member type."); break; } } // OK, we should have built all the members. Now go through and make sure the discriminant // offsets have been copied over to the schemas and annotations have been applied. root.finishGroup(); for (auto member: allMembers) { kj::StringPtr targetsFlagName; if (member->isParam) { targetsFlagName = "targetsParam"; } else { switch (member->declKind) { case Declaration::FIELD: targetsFlagName = "targetsField"; break; case Declaration::UNION: member->finishGroup(); targetsFlagName = "targetsUnion"; break; case Declaration::GROUP: member->finishGroup(); targetsFlagName = "targetsGroup"; break; default: KJ_FAIL_ASSERT("Unexpected member type."); break; } } member->getSchema().adoptAnnotations(translator.compileAnnotationApplications( member->declAnnotations, targetsFlagName)); } // And fill in the sizes. structBuilder.setDataWordCount(layout.getTop().dataWordCount); structBuilder.setPointerCount(layout.getTop().pointerCount); structBuilder.setPreferredListEncoding(schema::ElementSize::INLINE_COMPOSITE); for (auto& group: translator.groups) { auto groupBuilder = group.node.get().getStruct(); groupBuilder.setDataWordCount(structBuilder.getDataWordCount()); groupBuilder.setPointerCount(structBuilder.getPointerCount()); groupBuilder.setPreferredListEncoding(structBuilder.getPreferredListEncoding()); } } }; void NodeTranslator::compileStruct(Void decl, List::Reader members, schema::Node::Builder builder) { StructTranslator(*this, ImplicitParams::none()) .translate(decl, members, builder, sourceInfo.get()); } // ------------------------------------------------------------------- void NodeTranslator::compileInterface(Declaration::Interface::Reader decl, List::Reader members, schema::Node::Builder builder) { auto interfaceBuilder = builder.initInterface(); auto superclassesDecl = decl.getSuperclasses(); auto superclassesBuilder = interfaceBuilder.initSuperclasses(superclassesDecl.size()); for (uint i: kj::indices(superclassesDecl)) { auto superclass = superclassesDecl[i]; KJ_IF_MAYBE(decl, compileDeclExpression(superclass, ImplicitParams::none())) { KJ_IF_MAYBE(kind, decl->getKind()) { if (*kind == Declaration::INTERFACE) { auto s = superclassesBuilder[i]; s.setId(decl->getIdAndFillBrand([&]() { return s.initBrand(); })); } else { decl->addError(errorReporter, kj::str( "'", decl->toString(), "' is not an interface.")); } } else { // A variable? decl->addError(errorReporter, kj::str( "'", decl->toString(), "' is an unbound generic parameter. Currently we don't support " "extending these.")); } } } // maps ordinal -> (code order, declaration) std::multimap> methods; uint codeOrder = 0; for (auto member: members) { if (member.isMethod()) { methods.insert( std::make_pair(member.getId().getOrdinal().getValue(), std::make_pair(codeOrder++, member))); } } auto list = interfaceBuilder.initMethods(methods.size()); auto sourceInfoList = sourceInfo.get().initMembers(methods.size()); uint i = 0; DuplicateOrdinalDetector dupDetector(errorReporter); for (auto& entry: methods) { uint codeOrder = entry.second.first; Declaration::Reader methodDecl = entry.second.second; auto methodReader = methodDecl.getMethod(); auto ordinalDecl = methodDecl.getId().getOrdinal(); dupDetector.check(ordinalDecl); uint16_t ordinal = ordinalDecl.getValue(); if (methodDecl.hasDocComment()) { sourceInfoList[i].setDocComment(methodDecl.getDocComment()); } auto methodBuilder = list[i++]; methodBuilder.setName(methodDecl.getName().getValue()); methodBuilder.setCodeOrder(codeOrder); auto implicits = methodDecl.getParameters(); auto implicitsBuilder = methodBuilder.initImplicitParameters(implicits.size()); for (auto i: kj::indices(implicits)) { implicitsBuilder[i].setName(implicits[i].getName()); } auto params = methodReader.getParams(); if (params.isStream()) { errorReporter.addErrorOn(params, "'stream' can only appear after '->', not before."); } methodBuilder.setParamStructType(compileParamList( methodDecl.getName().getValue(), ordinal, false, params, implicits, [&]() { return methodBuilder.initParamBrand(); })); auto results = methodReader.getResults(); Declaration::ParamList::Reader resultList; if (results.isExplicit()) { resultList = results.getExplicit(); } else { // We just stick with `resultList` uninitialized, which is equivalent to the default // instance. This works because `namedList` is the default kind of ParamList, and it will // default to an empty list. } methodBuilder.setResultStructType(compileParamList( methodDecl.getName().getValue(), ordinal, true, resultList, implicits, [&]() { return methodBuilder.initResultBrand(); })); methodBuilder.adoptAnnotations(compileAnnotationApplications( methodDecl.getAnnotations(), "targetsMethod")); } } template uint64_t NodeTranslator::compileParamList( kj::StringPtr methodName, uint16_t ordinal, bool isResults, Declaration::ParamList::Reader paramList, typename List::Reader implicitParams, InitBrandFunc&& initBrand) { switch (paramList.which()) { case Declaration::ParamList::NAMED_LIST: { auto newStruct = orphanage.newOrphan(); auto newSourceInfo = orphanage.newOrphan(); auto builder = newStruct.get(); auto parent = wipNode.getReader(); kj::String typeName = kj::str(methodName, isResults ? "$Results" : "$Params"); builder.setId(generateMethodParamsId(parent.getId(), ordinal, isResults)); builder.setDisplayName(kj::str(parent.getDisplayName(), '.', typeName)); builder.setDisplayNamePrefixLength(builder.getDisplayName().size() - typeName.size()); builder.setIsGeneric(parent.getIsGeneric() || implicitParams.size() > 0); builder.setScopeId(0); // detached struct type builder.initStruct(); // Note that the struct we create here has a brand parameter list mirrioring the method's // implicit parameter list. Of course, fields inside the struct using the method's implicit // params as types actually need to refer to them as regular params, so we create an // ImplicitParams with a scopeId here. StructTranslator(*this, ImplicitParams { builder.getId(), implicitParams }) .translate(paramList.getNamedList(), builder, newSourceInfo.get()); uint64_t id = builder.getId(); paramStructs.add(AuxNode { kj::mv(newStruct), kj::mv(newSourceInfo) }); auto brand = localBrand->push(builder.getId(), implicitParams.size()); if (implicitParams.size() > 0) { auto implicitDecls = kj::heapArrayBuilder(implicitParams.size()); auto implicitBuilder = builder.initParameters(implicitParams.size()); for (auto i: kj::indices(implicitParams)) { auto param = implicitParams[i]; implicitDecls.add(BrandedDecl::implicitMethodParam(i)); implicitBuilder[i].setName(param.getName()); } brand->setParams(implicitDecls.finish(), Declaration::STRUCT, Expression::Reader()); } brand->compile(initBrand); return id; } case Declaration::ParamList::TYPE: KJ_IF_MAYBE(target, compileDeclExpression( paramList.getType(), ImplicitParams { 0, implicitParams })) { KJ_IF_MAYBE(kind, target->getKind()) { if (*kind == Declaration::STRUCT) { return target->getIdAndFillBrand(kj::fwd(initBrand)); } else { errorReporter.addErrorOn( paramList.getType(), kj::str("'", expressionString(paramList.getType()), "' is not a struct type.")); } } else { // A variable? target->addError(errorReporter, "Cannot use generic parameter as whole input or output of a method. Instead, " "use a parameter/result list containing a field with this type."); return 0; } } return 0; case Declaration::ParamList::STREAM: KJ_IF_MAYBE(streamCapnp, resolver.resolveImport("/capnp/stream.capnp")) { if (streamCapnp->resolver->resolveMember("StreamResult") == nullptr) { errorReporter.addErrorOn(paramList, "The version of '/capnp/stream.capnp' found in your import path does not appear " "to be the official one; it is missing the declaration of StreamResult."); } } else { errorReporter.addErrorOn(paramList, "A method declaration uses streaming, but '/capnp/stream.capnp' is not found " "in the import path. This is a standard file that should always be installed " "with the Cap'n Proto compiler."); } return typeId(); } KJ_UNREACHABLE; } // ------------------------------------------------------------------- kj::Maybe NodeTranslator::compileDeclExpression( Expression::Reader source, ImplicitParams implicitMethodParams) { return localBrand->compileDeclExpression(source, resolver, implicitMethodParams); } /* static */ kj::Maybe NodeTranslator::compileDecl( uint64_t scopeId, uint scopeParameterCount, Resolver& resolver, ErrorReporter& errorReporter, Expression::Reader expression, schema::Brand::Builder brandBuilder) { auto scope = kj::refcounted(errorReporter, scopeId, scopeParameterCount, resolver); KJ_IF_MAYBE(decl, scope->compileDeclExpression(expression, resolver, ImplicitParams::none())) { return decl->asResolveResult(scope->getScopeId(), brandBuilder); } else { return nullptr; } } bool NodeTranslator::compileType(Expression::Reader source, schema::Type::Builder target, ImplicitParams implicitMethodParams) { KJ_IF_MAYBE(decl, compileDeclExpression(source, implicitMethodParams)) { return decl->compileAsType(errorReporter, target); } else { return false; } } // ------------------------------------------------------------------- void NodeTranslator::compileDefaultDefaultValue( schema::Type::Reader type, schema::Value::Builder target) { switch (type.which()) { case schema::Type::VOID: target.setVoid(); break; case schema::Type::BOOL: target.setBool(false); break; case schema::Type::INT8: target.setInt8(0); break; case schema::Type::INT16: target.setInt16(0); break; case schema::Type::INT32: target.setInt32(0); break; case schema::Type::INT64: target.setInt64(0); break; case schema::Type::UINT8: target.setUint8(0); break; case schema::Type::UINT16: target.setUint16(0); break; case schema::Type::UINT32: target.setUint32(0); break; case schema::Type::UINT64: target.setUint64(0); break; case schema::Type::FLOAT32: target.setFloat32(0); break; case schema::Type::FLOAT64: target.setFloat64(0); break; case schema::Type::ENUM: target.setEnum(0); break; case schema::Type::INTERFACE: target.setInterface(); break; // Bit of a hack: For Text/Data, we adopt a null orphan, which sets the field to null. // TODO(cleanup): Create a cleaner way to do this. case schema::Type::TEXT: target.adoptText(Orphan()); break; case schema::Type::DATA: target.adoptData(Orphan()); break; case schema::Type::STRUCT: target.initStruct(); break; case schema::Type::LIST: target.initList(); break; case schema::Type::ANY_POINTER: target.initAnyPointer(); break; } } void NodeTranslator::compileBootstrapValue( Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target, kj::Maybe typeScope) { // Start by filling in a default default value so that if for whatever reason we don't end up // initializing the value, this won't cause schema validation to fail. compileDefaultDefaultValue(type, target); switch (type.which()) { case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: unfinishedValues.add(UnfinishedValue { source, type, typeScope, target }); break; default: // Primitive value. (Note that the scope can't possibly matter since primitives are not // generic.) compileValue(source, type, typeScope.orDefault(Schema()), target, true); break; } } void NodeTranslator::compileValue(Expression::Reader source, schema::Type::Reader type, Schema typeScope, schema::Value::Builder target, bool isBootstrap) { class ResolverGlue: public ValueTranslator::Resolver { public: inline ResolverGlue(NodeTranslator& translator, bool isBootstrap) : translator(translator), isBootstrap(isBootstrap) {} kj::Maybe resolveConstant(Expression::Reader name) override { return translator.readConstant(name, isBootstrap); } kj::Maybe> readEmbed(LocatedText::Reader filename) override { return translator.readEmbed(filename); } private: NodeTranslator& translator; bool isBootstrap; }; ResolverGlue glue(*this, isBootstrap); ValueTranslator valueTranslator(glue, errorReporter, orphanage); KJ_IF_MAYBE(typeSchema, resolver.resolveBootstrapType(type, typeScope)) { kj::StringPtr fieldName = Schema::from() .getUnionFields()[static_cast(typeSchema->which())].getProto().getName(); KJ_IF_MAYBE(value, valueTranslator.compileValue(source, *typeSchema)) { if (typeSchema->isEnum()) { target.setEnum(value->getReader().as().getRaw()); } else { toDynamic(target).adopt(fieldName, kj::mv(*value)); } } } } kj::Maybe> ValueTranslator::compileValue(Expression::Reader src, Type type) { if (type.isAnyPointer()) { if (type.getBrandParameter() != nullptr || type.getImplicitParameter() != nullptr) { errorReporter.addErrorOn(src, "Cannot interpret value because the type is a generic type parameter which is not " "yet bound. We don't know what type to expect here."); return nullptr; } } Orphan result = compileValueInner(src, type); if (result.getType() == DynamicValue::UNKNOWN) { // Error already reported. return nullptr; } else if (matchesType(src, type, result)) { return kj::mv(result); } else { // If the expected type is a struct, we try matching its first field. if (type.isStruct()) { auto structType = type.asStruct(); auto fields = structType.getFields(); if (fields.size() > 0) { auto field = fields[0]; if (matchesType(src, field.getType(), result)) { // Success. Wrap in a struct. auto outer = orphanage.newOrphan(type.asStruct()); outer.get().adopt(field, kj::mv(result)); return Orphan(kj::mv(outer)); } } } // That didn't work, so this is just a type mismatch. errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); return nullptr; } } bool ValueTranslator::matchesType(Expression::Reader src, Type type, Orphan& result) { // compileValueInner() evaluated `src` and only used `type` as a hint in interpreting `src` if // `src`'s type wasn't already obvious. So, now we need to check that the resulting value // actually matches `type`. switch (result.getType()) { case DynamicValue::UNKNOWN: KJ_UNREACHABLE; case DynamicValue::VOID: return type.isVoid(); case DynamicValue::BOOL: return type.isBool(); case DynamicValue::INT: { int64_t value = result.getReader().as(); if (value < 0) { int64_t minValue; switch (type.which()) { case schema::Type::INT8: minValue = (int8_t)kj::minValue; break; case schema::Type::INT16: minValue = (int16_t)kj::minValue; break; case schema::Type::INT32: minValue = (int32_t)kj::minValue; break; case schema::Type::INT64: minValue = (int64_t)kj::minValue; break; case schema::Type::UINT8: minValue = (uint8_t)kj::minValue; break; case schema::Type::UINT16: minValue = (uint16_t)kj::minValue; break; case schema::Type::UINT32: minValue = (uint32_t)kj::minValue; break; case schema::Type::UINT64: minValue = (uint64_t)kj::minValue; break; case schema::Type::FLOAT32: case schema::Type::FLOAT64: // Any integer is acceptable. minValue = (int64_t)kj::minValue; break; default: return false; } if (value < minValue) { errorReporter.addErrorOn(src, "Integer value out of range."); result = minValue; } return true; } } KJ_FALLTHROUGH; // value is positive, so we can just go on to the uint case below. case DynamicValue::UINT: { uint64_t maxValue; switch (type.which()) { case schema::Type::INT8: maxValue = (int8_t)kj::maxValue; break; case schema::Type::INT16: maxValue = (int16_t)kj::maxValue; break; case schema::Type::INT32: maxValue = (int32_t)kj::maxValue; break; case schema::Type::INT64: maxValue = (int64_t)kj::maxValue; break; case schema::Type::UINT8: maxValue = (uint8_t)kj::maxValue; break; case schema::Type::UINT16: maxValue = (uint16_t)kj::maxValue; break; case schema::Type::UINT32: maxValue = (uint32_t)kj::maxValue; break; case schema::Type::UINT64: maxValue = (uint64_t)kj::maxValue; break; case schema::Type::FLOAT32: case schema::Type::FLOAT64: // Any integer is acceptable. maxValue = (uint64_t)kj::maxValue; break; default: return false; } if (result.getReader().as() > maxValue) { errorReporter.addErrorOn(src, "Integer value out of range."); result = maxValue; } return true; } case DynamicValue::FLOAT: return type.isFloat32() || type.isFloat64(); case DynamicValue::TEXT: return type.isText(); case DynamicValue::DATA: return type.isData(); case DynamicValue::LIST: if (type.isList()) { return result.getReader().as().getSchema() == type.asList(); } else if (type.isAnyPointer()) { switch (type.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::ANY_KIND: case schema::Type::AnyPointer::Unconstrained::LIST: return true; case schema::Type::AnyPointer::Unconstrained::STRUCT: case schema::Type::AnyPointer::Unconstrained::CAPABILITY: return false; } KJ_UNREACHABLE; } else { return false; } case DynamicValue::ENUM: return type.isEnum() && result.getReader().as().getSchema() == type.asEnum(); case DynamicValue::STRUCT: if (type.isStruct()) { return result.getReader().as().getSchema() == type.asStruct(); } else if (type.isAnyPointer()) { switch (type.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::ANY_KIND: case schema::Type::AnyPointer::Unconstrained::STRUCT: return true; case schema::Type::AnyPointer::Unconstrained::LIST: case schema::Type::AnyPointer::Unconstrained::CAPABILITY: return false; } KJ_UNREACHABLE; } else { return false; } case DynamicValue::CAPABILITY: KJ_FAIL_ASSERT("Interfaces can't have literal values."); case DynamicValue::ANY_POINTER: KJ_FAIL_ASSERT("AnyPointers can't have literal values."); } KJ_UNREACHABLE; } Orphan ValueTranslator::compileValueInner(Expression::Reader src, Type type) { switch (src.which()) { case Expression::RELATIVE_NAME: { auto name = src.getRelativeName(); // The name is just a bare identifier. It may be a literal value or an enumerant. kj::StringPtr id = name.getValue(); if (type.isEnum()) { KJ_IF_MAYBE(enumerant, type.asEnum().findEnumerantByName(id)) { return DynamicEnum(*enumerant); } } else { // Interpret known constant values. if (id == "void") { return VOID; } else if (id == "true") { return true; } else if (id == "false") { return false; } else if (id == "nan") { return kj::nan(); } else if (id == "inf") { return kj::inf(); } } // Apparently not a literal. Try resolving it. KJ_IF_MAYBE(constValue, resolver.resolveConstant(src)) { return orphanage.newOrphanCopy(*constValue); } else { return nullptr; } } case Expression::ABSOLUTE_NAME: case Expression::IMPORT: case Expression::APPLICATION: case Expression::MEMBER: KJ_IF_MAYBE(constValue, resolver.resolveConstant(src)) { return orphanage.newOrphanCopy(*constValue); } else { return nullptr; } case Expression::EMBED: KJ_IF_MAYBE(data, resolver.readEmbed(src.getEmbed())) { switch (type.which()) { case schema::Type::TEXT: { // Sadly, we need to make a copy to add the NUL terminator. auto text = orphanage.newOrphan(data->size()); memcpy(text.get().begin(), data->begin(), data->size()); return kj::mv(text); } case schema::Type::DATA: // TODO(perf): It would arguably be neat to use orphanage.referenceExternalData(), // since typically the data is mmap()ed and this would avoid forcing a large file // to become memory-resident. However, we'd have to figure out who should own the // Array. Also, we'd have to deal with the possibility of misaligned data -- // though arguably in that case we know it's not mmap()ed so whatever. One more // thing: it would be neat to be able to reference text blobs this way too, if only // we could rely on the assumption that as long as the data doesn't end on a page // boundary, it will be zero-padded, thus giving us our NUL terminator (4095/4096 of // the time), but this seems to require documenting constraints on the underlying // file-reading interfaces. Hm. return orphanage.newOrphanCopy(Data::Reader(*data)); case schema::Type::STRUCT: { // We will almost certainly if (data->size() % sizeof(word) != 0) { errorReporter.addErrorOn(src, "Embedded file is not a valid Cap'n Proto message."); return nullptr; } kj::Array copy; kj::ArrayPtr words; if (reinterpret_cast(data->begin()) % sizeof(void*) == 0) { // Hooray, data is aligned. words = kj::ArrayPtr( reinterpret_cast(data->begin()), data->size() / sizeof(word)); } else { // Ugh, data not aligned. Make a copy. copy = kj::heapArray(data->size() / sizeof(word)); memcpy(copy.begin(), data->begin(), data->size()); words = copy; } ReaderOptions options; options.traversalLimitInWords = kj::maxValue; options.nestingLimit = kj::maxValue; FlatArrayMessageReader reader(words, options); return orphanage.newOrphanCopy(reader.getRoot(type.asStruct())); } default: errorReporter.addErrorOn(src, "Embeds can only be used when Text, Data, or a struct is expected."); return nullptr; } } else { return nullptr; } case Expression::POSITIVE_INT: return src.getPositiveInt(); case Expression::NEGATIVE_INT: { uint64_t nValue = src.getNegativeInt(); if (nValue > ((uint64_t)kj::maxValue >> 1) + 1) { errorReporter.addErrorOn(src, "Integer is too big to be negative."); return nullptr; } else { return kj::implicitCast(-nValue); } } case Expression::FLOAT: return src.getFloat(); break; case Expression::STRING: if (type.isData()) { Text::Reader text = src.getString(); return orphanage.newOrphanCopy(Data::Reader(text.asBytes())); } else { return orphanage.newOrphanCopy(src.getString()); } break; case Expression::BINARY: if (!type.isData()) { errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); return nullptr; } return orphanage.newOrphanCopy(src.getBinary()); case Expression::LIST: { if (!type.isList()) { errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); return nullptr; } auto listSchema = type.asList(); Type elementType = listSchema.getElementType(); auto srcList = src.getList(); Orphan result = orphanage.newOrphan(listSchema, srcList.size()); auto dstList = result.get(); for (uint i = 0; i < srcList.size(); i++) { KJ_IF_MAYBE(value, compileValue(srcList[i], elementType)) { dstList.adopt(i, kj::mv(*value)); } } return kj::mv(result); } case Expression::TUPLE: { if (!type.isStruct()) { errorReporter.addErrorOn(src, kj::str("Type mismatch; expected ", makeTypeName(type), ".")); return nullptr; } auto structSchema = type.asStruct(); Orphan result = orphanage.newOrphan(structSchema); fillStructValue(result.get(), src.getTuple()); return kj::mv(result); } case Expression::UNKNOWN: // Ignore earlier error. return nullptr; } KJ_UNREACHABLE; } void ValueTranslator::fillStructValue(DynamicStruct::Builder builder, List::Reader assignments) { for (auto assignment: assignments) { if (assignment.isNamed()) { auto fieldName = assignment.getNamed(); KJ_IF_MAYBE(field, builder.getSchema().findFieldByName(fieldName.getValue())) { auto fieldProto = field->getProto(); auto value = assignment.getValue(); switch (fieldProto.which()) { case schema::Field::SLOT: KJ_IF_MAYBE(compiledValue, compileValue(value, field->getType())) { builder.adopt(*field, kj::mv(*compiledValue)); } break; case schema::Field::GROUP: auto groupBuilder = builder.init(*field).as(); if (value.isTuple()) { fillStructValue(groupBuilder, value.getTuple()); } else { auto groupFields = groupBuilder.getSchema().getFields(); if (groupFields.size() > 0) { auto groupField = groupFields[0]; // Call compileValueInner() using the group's type as `type`. Since we already // established `value` is not a tuple, this will only return a valid result if // the value has unambiguous type. auto result = compileValueInner(value, field->getType()); // Does it match the first field? if (matchesType(value, groupField.getType(), result)) { groupBuilder.adopt(groupField, kj::mv(result)); break; } } errorReporter.addErrorOn(value, "Type mismatch; expected group."); } break; } } else { errorReporter.addErrorOn(fieldName, kj::str( "Struct has no field named '", fieldName.getValue(), "'.")); } } else { errorReporter.addErrorOn(assignment.getValue(), kj::str("Missing field name.")); } } } kj::String ValueTranslator::makeNodeName(Schema schema) { schema::Node::Reader proto = schema.getProto(); return kj::str(proto.getDisplayName().slice(proto.getDisplayNamePrefixLength())); } kj::String ValueTranslator::makeTypeName(Type type) { switch (type.which()) { case schema::Type::VOID: return kj::str("Void"); case schema::Type::BOOL: return kj::str("Bool"); case schema::Type::INT8: return kj::str("Int8"); case schema::Type::INT16: return kj::str("Int16"); case schema::Type::INT32: return kj::str("Int32"); case schema::Type::INT64: return kj::str("Int64"); case schema::Type::UINT8: return kj::str("UInt8"); case schema::Type::UINT16: return kj::str("UInt16"); case schema::Type::UINT32: return kj::str("UInt32"); case schema::Type::UINT64: return kj::str("UInt64"); case schema::Type::FLOAT32: return kj::str("Float32"); case schema::Type::FLOAT64: return kj::str("Float64"); case schema::Type::TEXT: return kj::str("Text"); case schema::Type::DATA: return kj::str("Data"); case schema::Type::LIST: return kj::str("List(", makeTypeName(type.asList().getElementType()), ")"); case schema::Type::ENUM: return makeNodeName(type.asEnum()); case schema::Type::STRUCT: return makeNodeName(type.asStruct()); case schema::Type::INTERFACE: return makeNodeName(type.asInterface()); case schema::Type::ANY_POINTER: return kj::str("AnyPointer"); } KJ_UNREACHABLE; } kj::Maybe NodeTranslator::readConstant( Expression::Reader source, bool isBootstrap) { // Look up the constant decl. BrandedDecl constDecl = nullptr; KJ_IF_MAYBE(decl, compileDeclExpression(source, ImplicitParams::none())) { constDecl = *decl; } else { // Lookup will have reported an error. return nullptr; } // Is it a constant? if(constDecl.getKind().orDefault(Declaration::FILE) != Declaration::CONST) { errorReporter.addErrorOn(source, kj::str("'", expressionString(source), "' does not refer to a constant.")); return nullptr; } // Extract the ID and brand. MallocMessageBuilder builder(256); auto constBrand = builder.getRoot(); uint64_t id = constDecl.getIdAndFillBrand([&]() { return constBrand; }); // Look up the schema -- we'll need this to compile the constant's type. Schema constSchema; KJ_IF_MAYBE(s, resolver.resolveBootstrapSchema(id, constBrand)) { constSchema = *s; } else { // The constant's schema is broken for reasons already reported. return nullptr; } // If we're bootstrapping, then we know we're expecting a primitive value, so if the // constant turns out to be non-primitive, we'll error out anyway. If we're not // bootstrapping, we may be compiling a non-primitive value and so we need the final // version of the constant to make sure its value is filled in. schema::Node::Reader proto = constSchema.getProto(); if (!isBootstrap) { KJ_IF_MAYBE(finalProto, resolver.resolveFinalSchema(id)) { proto = *finalProto; } else { // The constant's final schema is broken for reasons already reported. return nullptr; } } auto constReader = proto.getConst(); auto dynamicConst = toDynamic(constReader.getValue()); auto constValue = dynamicConst.get(KJ_ASSERT_NONNULL(dynamicConst.which())); if (constValue.getType() == DynamicValue::ANY_POINTER) { // We need to assign an appropriate schema to this pointer. AnyPointer::Reader objValue = constValue.as(); auto constType = constSchema.asConst().getType(); switch (constType.which()) { case schema::Type::STRUCT: constValue = objValue.getAs(constType.asStruct()); break; case schema::Type::LIST: constValue = objValue.getAs(constType.asList()); break; case schema::Type::ANY_POINTER: // Fine as-is. break; default: KJ_FAIL_ASSERT("Unrecognized AnyPointer-typed member of schema::Value."); break; } } if (source.isRelativeName()) { // A fully unqualified identifier looks like it might refer to a constant visible in the // current scope, but if that's really what the user wanted, we want them to use a // qualified name to make it more obvious. Report an error. KJ_IF_MAYBE(scope, resolver.resolveBootstrapSchema(proto.getScopeId(), schema::Brand::Reader())) { auto scopeReader = scope->getProto(); kj::StringPtr parent; if (scopeReader.isFile()) { parent = ""; } else { parent = scopeReader.getDisplayName().slice(scopeReader.getDisplayNamePrefixLength()); } kj::StringPtr id = source.getRelativeName().getValue(); errorReporter.addErrorOn(source, kj::str( "Constant names must be qualified to avoid confusion. Please replace '", expressionString(source), "' with '", parent, ".", id, "', if that's what you intended.")); } } return constValue; } kj::Maybe> NodeTranslator::readEmbed(LocatedText::Reader filename) { KJ_IF_MAYBE(data, resolver.readEmbed(filename.getValue())) { return kj::mv(*data); } else { errorReporter.addErrorOn(filename, kj::str("Couldn't read file for embed: ", filename.getValue())); return nullptr; } } Orphan> NodeTranslator::compileAnnotationApplications( List::Reader annotations, kj::StringPtr targetsFlagName) { if (annotations.size() == 0 || !compileAnnotations) { // Return null. return Orphan>(); } auto result = orphanage.newOrphan>(annotations.size()); auto builder = result.get(); for (uint i = 0; i < annotations.size(); i++) { Declaration::AnnotationApplication::Reader annotation = annotations[i]; schema::Annotation::Builder annotationBuilder = builder[i]; // Set the annotation's value to void in case we fail to produce something better below. annotationBuilder.initValue().setVoid(); auto name = annotation.getName(); KJ_IF_MAYBE(decl, compileDeclExpression(name, ImplicitParams::none())) { KJ_IF_MAYBE(kind, decl->getKind()) { if (*kind != Declaration::ANNOTATION) { errorReporter.addErrorOn(name, kj::str( "'", expressionString(name), "' is not an annotation.")); } else { annotationBuilder.setId(decl->getIdAndFillBrand( [&]() { return annotationBuilder.initBrand(); })); KJ_IF_MAYBE(annotationSchema, resolver.resolveBootstrapSchema(annotationBuilder.getId(), annotationBuilder.getBrand())) { auto node = annotationSchema->getProto().getAnnotation(); if (!toDynamic(node).get(targetsFlagName).as()) { errorReporter.addErrorOn(name, kj::str( "'", expressionString(name), "' cannot be applied to this kind of declaration.")); } // Interpret the value. auto value = annotation.getValue(); switch (value.which()) { case Declaration::AnnotationApplication::Value::NONE: // No value, i.e. void. if (node.getType().isVoid()) { annotationBuilder.getValue().setVoid(); } else { errorReporter.addErrorOn(name, kj::str( "'", expressionString(name), "' requires a value.")); compileDefaultDefaultValue(node.getType(), annotationBuilder.getValue()); } break; case Declaration::AnnotationApplication::Value::EXPRESSION: compileBootstrapValue(value.getExpression(), node.getType(), annotationBuilder.getValue(), *annotationSchema); break; } } } } else { errorReporter.addErrorOn(name, kj::str( "'", expressionString(name), "' is not an annotation.")); } } } return result; } } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/lexer.c++0000644000175000017500000003113414712011043022050 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "lexer.h" #include #include namespace capnp { namespace compiler { namespace p = kj::parse; bool lex(kj::ArrayPtr input, LexedStatements::Builder result, ErrorReporter& errorReporter) { Lexer lexer(Orphanage::getForMessageContaining(result), errorReporter); auto parser = p::sequence(lexer.getParsers().statementSequence, p::endOfInput); Lexer::ParserInput parserInput(input.begin(), input.end()); kj::Maybe>> parseOutput = parser(parserInput); KJ_IF_MAYBE(output, parseOutput) { auto l = result.initStatements(output->size()); for (uint i = 0; i < output->size(); i++) { l.adoptWithCaveats(i, kj::mv((*output)[i])); } return true; } else { uint32_t best = parserInput.getBest(); errorReporter.addError(best, best, kj::str("Parse error.")); return false; } } bool lex(kj::ArrayPtr input, LexedTokens::Builder result, ErrorReporter& errorReporter) { Lexer lexer(Orphanage::getForMessageContaining(result), errorReporter); auto parser = p::sequence(lexer.getParsers().tokenSequence, p::endOfInput); Lexer::ParserInput parserInput(input.begin(), input.end()); kj::Maybe>> parseOutput = parser(parserInput); KJ_IF_MAYBE(output, parseOutput) { auto l = result.initTokens(output->size()); for (uint i = 0; i < output->size(); i++) { l.adoptWithCaveats(i, kj::mv((*output)[i])); } return true; } else { uint32_t best = parserInput.getBest(); errorReporter.addError(best, best, kj::str("Parse error.")); return false; } } namespace { typedef p::Span Location; Token::Builder initTok(Orphan& t, const Location& loc) { auto builder = t.get(); builder.setStartByte(loc.begin()); builder.setEndByte(loc.end()); return builder; } void buildTokenSequenceList(List>::Builder builder, kj::Array>>&& items) { for (uint i = 0; i < items.size(); i++) { auto& item = items[i]; auto itemBuilder = builder.init(i, item.size()); for (uint j = 0; j < item.size(); j++) { itemBuilder.adoptWithCaveats(j, kj::mv(item[j])); } } } void attachDocComment(Statement::Builder statement, kj::Array&& comment) { size_t size = 0; for (auto& line: comment) { size += line.size() + 1; // include newline } Text::Builder builder = statement.initDocComment(size); char* pos = builder.begin(); for (auto& line: comment) { memcpy(pos, line.begin(), line.size()); pos += line.size(); *pos++ = '\n'; } KJ_ASSERT(pos == builder.end()); } constexpr auto discardComment = sequence(p::exactChar<'#'>(), p::discard(p::many(p::discard(p::anyOfChars("\n").invert()))), p::oneOf(p::exactChar<'\n'>(), p::endOfInput)); constexpr auto saveComment = sequence(p::exactChar<'#'>(), p::discard(p::optional(p::exactChar<' '>())), p::charsToString(p::many(p::anyOfChars("\n").invert())), p::oneOf(p::exactChar<'\n'>(), p::endOfInput)); constexpr auto utf8Bom = sequence(p::exactChar<'\xef'>(), p::exactChar<'\xbb'>(), p::exactChar<'\xbf'>()); constexpr auto bomsAndWhitespace = sequence(p::discardWhitespace, p::discard(p::many(sequence(utf8Bom, p::discardWhitespace)))); constexpr auto commentsAndWhitespace = sequence(bomsAndWhitespace, p::discard(p::many(sequence(discardComment, bomsAndWhitespace)))); constexpr auto discardLineWhitespace = p::discard(p::many(p::discard(p::whitespaceChar.invert().orAny("\r\n").invert()))); constexpr auto newline = p::oneOf( p::exactChar<'\n'>(), sequence(p::exactChar<'\r'>(), p::discard(p::optional(p::exactChar<'\n'>())))); constexpr auto docComment = p::optional(p::sequence( discardLineWhitespace, p::discard(p::optional(newline)), p::oneOrMore(p::sequence(discardLineWhitespace, saveComment)))); // Parses a set of comment lines preceded by at most one newline and with no intervening blank // lines. } // namespace Lexer::Lexer(Orphanage orphanageParam, ErrorReporter& errorReporter) : orphanage(orphanageParam) { // Note that because passing an lvalue to a parser constructor uses it by-referencee, it's safe // for us to use parsers.tokenSequence even though we haven't yet constructed it. auto& tokenSequence = parsers.tokenSequence; auto& commaDelimitedList = arena.copy(p::transform( p::sequence(tokenSequence, p::many(p::sequence(p::exactChar<','>(), tokenSequence))), [](kj::Array>&& first, kj::Array>>&& rest) -> kj::Array>> { if (first == nullptr && rest == nullptr) { // Completely empty list. return nullptr; } else { uint restSize = rest.size(); if (restSize > 0 && rest[restSize - 1] == nullptr) { // Allow for trailing commas by shortening the list by one item if the final token is // nullptr restSize--; } auto result = kj::heapArrayBuilder>>(1 + restSize); // first+rest result.add(kj::mv(first)); for (uint i = 0; i < restSize ; i++) { result.add(kj::mv(rest[i])); } return result.finish(); } })); auto& token = arena.copy(p::oneOf( p::transformWithLocation(p::identifier, [this](Location loc, kj::String name) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setIdentifier(name); return t; }), p::transformWithLocation(p::doubleQuotedString, [this](Location loc, kj::String text) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setStringLiteral(text); return t; }), p::transformWithLocation( sequence(p::exactChar<'`'>(), p::many(p::anyOfChars("\r\n").invert())), [this](Location loc, kj::Array text) -> Orphan { // Backtick-quoted line. Note that we assume either `\r` or `\n` is a valid line // ending (to cover all known line ending formats) but we replace the line ending // with `\n`. This way, changing the line endings of your source code doesn't affect // the compiled code. auto t = orphanage.newOrphan(); // Append '\n' to the text. auto out = initTok(t, loc).initStringLiteral(text.size() + 1); memcpy(out.begin(), text.begin(), text.size()); out[out.size() - 1] = '\n'; return t; }), p::transformWithLocation(p::doubleQuotedHexBinary, [this](Location loc, kj::Array data) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setBinaryLiteral(data); return t; }), p::transformWithLocation(p::integer, [this](Location loc, uint64_t i) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setIntegerLiteral(i); return t; }), p::transformWithLocation(p::number, [this](Location loc, double x) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setFloatLiteral(x); return t; }), p::transformWithLocation( p::charsToString(p::oneOrMore(p::anyOfChars("!$%&*+-./:<=>?@^|~"))), [this](Location loc, kj::String text) -> Orphan { auto t = orphanage.newOrphan(); initTok(t, loc).setOperator(text); return t; }), p::transformWithLocation( sequence(p::exactChar<'('>(), commaDelimitedList, p::exactChar<')'>()), [this](Location loc, kj::Array>>&& items) -> Orphan { auto t = orphanage.newOrphan(); buildTokenSequenceList( initTok(t, loc).initParenthesizedList(items.size()), kj::mv(items)); return t; }), p::transformWithLocation( sequence(p::exactChar<'['>(), commaDelimitedList, p::exactChar<']'>()), [this](Location loc, kj::Array>>&& items) -> Orphan { auto t = orphanage.newOrphan(); buildTokenSequenceList( initTok(t, loc).initBracketedList(items.size()), kj::mv(items)); return t; }), p::transformOrReject(p::transformWithLocation( p::oneOf(sequence(p::exactChar<'\xff'>(), p::exactChar<'\xfe'>()), sequence(p::exactChar<'\xfe'>(), p::exactChar<'\xff'>()), sequence(p::exactChar<'\x00'>())), [&errorReporter](Location loc) -> kj::Maybe> { errorReporter.addError(loc.begin(), loc.end(), "Non-UTF-8 input detected. Cap'n Proto schema files must be UTF-8 text."); return nullptr; }), [](kj::Maybe> param) { return param; }))); parsers.tokenSequence = arena.copy(p::sequence( commentsAndWhitespace, p::many(p::sequence(token, commentsAndWhitespace)))); auto& statementSequence = parsers.statementSequence; auto& statementEnd = arena.copy(p::oneOf( transform(p::sequence(p::exactChar<';'>(), docComment), [this](kj::Maybe>&& comment) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); KJ_IF_MAYBE(c, comment) { attachDocComment(builder, kj::mv(*c)); } builder.setLine(); return result; }), transform( p::sequence(p::exactChar<'{'>(), docComment, statementSequence, p::exactChar<'}'>(), docComment), [this](kj::Maybe>&& comment, kj::Array>&& statements, kj::Maybe>&& lateComment) -> Orphan { auto result = orphanage.newOrphan(); auto builder = result.get(); KJ_IF_MAYBE(c, comment) { attachDocComment(builder, kj::mv(*c)); } else KJ_IF_MAYBE(c, lateComment) { attachDocComment(builder, kj::mv(*c)); } auto list = builder.initBlock(statements.size()); for (uint i = 0; i < statements.size(); i++) { list.adoptWithCaveats(i, kj::mv(statements[i])); } return result; }) )); auto& statement = arena.copy(p::transformWithLocation(p::sequence(tokenSequence, statementEnd), [](Location loc, kj::Array>&& tokens, Orphan&& statement) { auto builder = statement.get(); auto tokensBuilder = builder.initTokens(tokens.size()); for (uint i = 0; i < tokens.size(); i++) { tokensBuilder.adoptWithCaveats(i, kj::mv(tokens[i])); } builder.setStartByte(loc.begin()); builder.setEndByte(loc.end()); return kj::mv(statement); })); parsers.statementSequence = arena.copy(sequence( commentsAndWhitespace, many(sequence(statement, commentsAndWhitespace)))); parsers.token = token; parsers.statement = statement; parsers.emptySpace = commentsAndWhitespace; } Lexer::~Lexer() noexcept(false) {} } // namespace compiler } // namespace capnp capnproto-c++-1.1.0/src/capnp/compiler/lexer.capnp.h0000644000175000017500000015466614731562162023065 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: lexer.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(91cc55cd57de5419); CAPNP_DECLARE_SCHEMA(c6725e678d60fa37); CAPNP_DECLARE_SCHEMA(9e69a92512b19d18); CAPNP_DECLARE_SCHEMA(a11f97b9d6c73dd4); } // namespace schemas } // namespace capnp namespace capnp { namespace compiler { struct Token { Token() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { IDENTIFIER, STRING_LITERAL, INTEGER_LITERAL, FLOAT_LITERAL, OPERATOR, PARENTHESIZED_LIST, BRACKETED_LIST, BINARY_LITERAL, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(91cc55cd57de5419, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Statement { Statement() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { LINE, BLOCK, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c6725e678d60fa37, 2, 3) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct LexedTokens { LexedTokens() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9e69a92512b19d18, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct LexedStatements { LexedStatements() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(a11f97b9d6c73dd4, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class Token::Reader { public: typedef Token Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isIdentifier() const; inline bool hasIdentifier() const; inline ::capnp::Text::Reader getIdentifier() const; inline bool isStringLiteral() const; inline bool hasStringLiteral() const; inline ::capnp::Text::Reader getStringLiteral() const; inline bool isIntegerLiteral() const; inline ::uint64_t getIntegerLiteral() const; inline bool isFloatLiteral() const; inline double getFloatLiteral() const; inline bool isOperator() const; inline bool hasOperator() const; inline ::capnp::Text::Reader getOperator() const; inline bool isParenthesizedList() const; inline bool hasParenthesizedList() const; inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader getParenthesizedList() const; inline bool isBracketedList() const; inline bool hasBracketedList() const; inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader getBracketedList() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool isBinaryLiteral() const; inline bool hasBinaryLiteral() const; inline ::capnp::Data::Reader getBinaryLiteral() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Token::Builder { public: typedef Token Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isIdentifier(); inline bool hasIdentifier(); inline ::capnp::Text::Builder getIdentifier(); inline void setIdentifier( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initIdentifier(unsigned int size); inline void adoptIdentifier(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownIdentifier(); inline bool isStringLiteral(); inline bool hasStringLiteral(); inline ::capnp::Text::Builder getStringLiteral(); inline void setStringLiteral( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initStringLiteral(unsigned int size); inline void adoptStringLiteral(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownStringLiteral(); inline bool isIntegerLiteral(); inline ::uint64_t getIntegerLiteral(); inline void setIntegerLiteral( ::uint64_t value); inline bool isFloatLiteral(); inline double getFloatLiteral(); inline void setFloatLiteral(double value); inline bool isOperator(); inline bool hasOperator(); inline ::capnp::Text::Builder getOperator(); inline void setOperator( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initOperator(unsigned int size); inline void adoptOperator(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownOperator(); inline bool isParenthesizedList(); inline bool hasParenthesizedList(); inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder getParenthesizedList(); inline void setParenthesizedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value); inline void setParenthesizedList(::kj::ArrayPtr::Reader> value); inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder initParenthesizedList(unsigned int size); inline void adoptParenthesizedList(::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> disownParenthesizedList(); inline bool isBracketedList(); inline bool hasBracketedList(); inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder getBracketedList(); inline void setBracketedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value); inline void setBracketedList(::kj::ArrayPtr::Reader> value); inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder initBracketedList(unsigned int size); inline void adoptBracketedList(::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> disownBracketedList(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool isBinaryLiteral(); inline bool hasBinaryLiteral(); inline ::capnp::Data::Builder getBinaryLiteral(); inline void setBinaryLiteral( ::capnp::Data::Reader value); inline ::capnp::Data::Builder initBinaryLiteral(unsigned int size); inline void adoptBinaryLiteral(::capnp::Orphan< ::capnp::Data>&& value); inline ::capnp::Orphan< ::capnp::Data> disownBinaryLiteral(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Token::Pipeline { public: typedef Token Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Statement::Reader { public: typedef Statement Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool hasTokens() const; inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader getTokens() const; inline bool isLine() const; inline ::capnp::Void getLine() const; inline bool isBlock() const; inline bool hasBlock() const; inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader getBlock() const; inline bool hasDocComment() const; inline ::capnp::Text::Reader getDocComment() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Statement::Builder { public: typedef Statement Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool hasTokens(); inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder getTokens(); inline void setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder initTokens(unsigned int size); inline void adoptTokens(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> disownTokens(); inline bool isLine(); inline ::capnp::Void getLine(); inline void setLine( ::capnp::Void value = ::capnp::VOID); inline bool isBlock(); inline bool hasBlock(); inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder getBlock(); inline void setBlock( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder initBlock(unsigned int size); inline void adoptBlock(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> disownBlock(); inline bool hasDocComment(); inline ::capnp::Text::Builder getDocComment(); inline void setDocComment( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initDocComment(unsigned int size); inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Statement::Pipeline { public: typedef Statement Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class LexedTokens::Reader { public: typedef LexedTokens Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasTokens() const; inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader getTokens() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class LexedTokens::Builder { public: typedef LexedTokens Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasTokens(); inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder getTokens(); inline void setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder initTokens(unsigned int size); inline void adoptTokens(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> disownTokens(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class LexedTokens::Pipeline { public: typedef LexedTokens Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class LexedStatements::Reader { public: typedef LexedStatements Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasStatements() const; inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader getStatements() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class LexedStatements::Builder { public: typedef LexedStatements Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasStatements(); inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder getStatements(); inline void setStatements( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder initStatements(unsigned int size); inline void adoptStatements(::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> disownStatements(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class LexedStatements::Pipeline { public: typedef LexedStatements Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline ::capnp::compiler::Token::Which Token::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Token::Which Token::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Token::Reader::isIdentifier() const { return which() == Token::IDENTIFIER; } inline bool Token::Builder::isIdentifier() { return which() == Token::IDENTIFIER; } inline bool Token::Reader::hasIdentifier() const { if (which() != Token::IDENTIFIER) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasIdentifier() { if (which() != Token::IDENTIFIER) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Token::Reader::getIdentifier() const { KJ_IREQUIRE((which() == Token::IDENTIFIER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Token::Builder::getIdentifier() { KJ_IREQUIRE((which() == Token::IDENTIFIER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setIdentifier( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Token::Builder::initIdentifier(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptIdentifier( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::IDENTIFIER); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownIdentifier() { KJ_IREQUIRE((which() == Token::IDENTIFIER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Token::Reader::isStringLiteral() const { return which() == Token::STRING_LITERAL; } inline bool Token::Builder::isStringLiteral() { return which() == Token::STRING_LITERAL; } inline bool Token::Reader::hasStringLiteral() const { if (which() != Token::STRING_LITERAL) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasStringLiteral() { if (which() != Token::STRING_LITERAL) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Token::Reader::getStringLiteral() const { KJ_IREQUIRE((which() == Token::STRING_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Token::Builder::getStringLiteral() { KJ_IREQUIRE((which() == Token::STRING_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setStringLiteral( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Token::Builder::initStringLiteral(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptStringLiteral( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::STRING_LITERAL); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownStringLiteral() { KJ_IREQUIRE((which() == Token::STRING_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Token::Reader::isIntegerLiteral() const { return which() == Token::INTEGER_LITERAL; } inline bool Token::Builder::isIntegerLiteral() { return which() == Token::INTEGER_LITERAL; } inline ::uint64_t Token::Reader::getIntegerLiteral() const { KJ_IREQUIRE((which() == Token::INTEGER_LITERAL), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Token::Builder::getIntegerLiteral() { KJ_IREQUIRE((which() == Token::INTEGER_LITERAL), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Token::Builder::setIntegerLiteral( ::uint64_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::INTEGER_LITERAL); _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Token::Reader::isFloatLiteral() const { return which() == Token::FLOAT_LITERAL; } inline bool Token::Builder::isFloatLiteral() { return which() == Token::FLOAT_LITERAL; } inline double Token::Reader::getFloatLiteral() const { KJ_IREQUIRE((which() == Token::FLOAT_LITERAL), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline double Token::Builder::getFloatLiteral() { KJ_IREQUIRE((which() == Token::FLOAT_LITERAL), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Token::Builder::setFloatLiteral(double value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::FLOAT_LITERAL); _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Token::Reader::isOperator() const { return which() == Token::OPERATOR; } inline bool Token::Builder::isOperator() { return which() == Token::OPERATOR; } inline bool Token::Reader::hasOperator() const { if (which() != Token::OPERATOR) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasOperator() { if (which() != Token::OPERATOR) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Token::Reader::getOperator() const { KJ_IREQUIRE((which() == Token::OPERATOR), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Token::Builder::getOperator() { KJ_IREQUIRE((which() == Token::OPERATOR), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setOperator( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Token::Builder::initOperator(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptOperator( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::OPERATOR); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Token::Builder::disownOperator() { KJ_IREQUIRE((which() == Token::OPERATOR), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Token::Reader::isParenthesizedList() const { return which() == Token::PARENTHESIZED_LIST; } inline bool Token::Builder::isParenthesizedList() { return which() == Token::PARENTHESIZED_LIST; } inline bool Token::Reader::hasParenthesizedList() const { if (which() != Token::PARENTHESIZED_LIST) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasParenthesizedList() { if (which() != Token::PARENTHESIZED_LIST) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader Token::Reader::getParenthesizedList() const { KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::getParenthesizedList() { KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setParenthesizedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline void Token::Builder::setParenthesizedList(::kj::ArrayPtr::Reader> value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::initParenthesizedList(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptParenthesizedList( ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::PARENTHESIZED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> Token::Builder::disownParenthesizedList() { KJ_IREQUIRE((which() == Token::PARENTHESIZED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Token::Reader::isBracketedList() const { return which() == Token::BRACKETED_LIST; } inline bool Token::Builder::isBracketedList() { return which() == Token::BRACKETED_LIST; } inline bool Token::Reader::hasBracketedList() const { if (which() != Token::BRACKETED_LIST) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasBracketedList() { if (which() != Token::BRACKETED_LIST) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader Token::Reader::getBracketedList() const { KJ_IREQUIRE((which() == Token::BRACKETED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::getBracketedList() { KJ_IREQUIRE((which() == Token::BRACKETED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setBracketedList( ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline void Token::Builder::setBracketedList(::kj::ArrayPtr::Reader> value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>::Builder Token::Builder::initBracketedList(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptBracketedList( ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BRACKETED_LIST); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>> Token::Builder::disownBracketedList() { KJ_IREQUIRE((which() == Token::BRACKETED_LIST), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>, ::capnp::Kind::LIST>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Token::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Token::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Token::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Token::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::uint32_t Token::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline void Token::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<4>() * ::capnp::ELEMENTS, value); } inline bool Token::Reader::isBinaryLiteral() const { return which() == Token::BINARY_LITERAL; } inline bool Token::Builder::isBinaryLiteral() { return which() == Token::BINARY_LITERAL; } inline bool Token::Reader::hasBinaryLiteral() const { if (which() != Token::BINARY_LITERAL) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Token::Builder::hasBinaryLiteral() { if (which() != Token::BINARY_LITERAL) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Data::Reader Token::Reader::getBinaryLiteral() const { KJ_IREQUIRE((which() == Token::BINARY_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Data::Builder Token::Builder::getBinaryLiteral() { KJ_IREQUIRE((which() == Token::BINARY_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Token::Builder::setBinaryLiteral( ::capnp::Data::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Data::Builder Token::Builder::initBinaryLiteral(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Token::Builder::adoptBinaryLiteral( ::capnp::Orphan< ::capnp::Data>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Token::BINARY_LITERAL); ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Data> Token::Builder::disownBinaryLiteral() { KJ_IREQUIRE((which() == Token::BINARY_LITERAL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::compiler::Statement::Which Statement::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::compiler::Statement::Which Statement::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Statement::Reader::hasTokens() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Statement::Builder::hasTokens() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader Statement::Reader::getTokens() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder Statement::Builder::getTokens() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Statement::Builder::setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder Statement::Builder::initTokens(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Statement::Builder::adoptTokens( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> Statement::Builder::disownTokens() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Statement::Reader::isLine() const { return which() == Statement::LINE; } inline bool Statement::Builder::isLine() { return which() == Statement::LINE; } inline ::capnp::Void Statement::Reader::getLine() const { KJ_IREQUIRE((which() == Statement::LINE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Statement::Builder::getLine() { KJ_IREQUIRE((which() == Statement::LINE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Statement::Builder::setLine( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::LINE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Statement::Reader::isBlock() const { return which() == Statement::BLOCK; } inline bool Statement::Builder::isBlock() { return which() == Statement::BLOCK; } inline bool Statement::Reader::hasBlock() const { if (which() != Statement::BLOCK) return false; return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Statement::Builder::hasBlock() { if (which() != Statement::BLOCK) return false; return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader Statement::Reader::getBlock() const { KJ_IREQUIRE((which() == Statement::BLOCK), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder Statement::Builder::getBlock() { KJ_IREQUIRE((which() == Statement::BLOCK), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Statement::Builder::setBlock( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder Statement::Builder::initBlock(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Statement::Builder::adoptBlock( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Statement::BLOCK); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> Statement::Builder::disownBlock() { KJ_IREQUIRE((which() == Statement::BLOCK), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Statement::Reader::hasDocComment() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Statement::Builder::hasDocComment() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Statement::Reader::getDocComment() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Statement::Builder::getDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Statement::Builder::setDocComment( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Statement::Builder::initDocComment(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), size); } inline void Statement::Builder::adoptDocComment( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Statement::Builder::disownDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::uint32_t Statement::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Statement::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Statement::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Statement::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Statement::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Statement::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool LexedTokens::Reader::hasTokens() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool LexedTokens::Builder::hasTokens() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader LexedTokens::Reader::getTokens() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder LexedTokens::Builder::getTokens() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void LexedTokens::Builder::setTokens( ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>::Builder LexedTokens::Builder::initTokens(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void LexedTokens::Builder::adoptTokens( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>> LexedTokens::Builder::disownTokens() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Token, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool LexedStatements::Reader::hasStatements() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool LexedStatements::Builder::hasStatements() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader LexedStatements::Reader::getStatements() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder LexedStatements::Builder::getStatements() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void LexedStatements::Builder::setStatements( ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>::Builder LexedStatements::Builder::initStatements(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void LexedStatements::Builder::adoptStatements( ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>> LexedStatements::Builder::disownStatements() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::compiler::Statement, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/grammar.capnp.c++0000644000175000017500000041047414712011043023467 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: grammar.capnp #include "grammar.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<66> b_e75816b56529d464 = { { 0, 0, 0, 0, 5, 0, 6, 0, 100, 212, 41, 101, 181, 22, 88, 231, 29, 0, 0, 0, 1, 0, 1, 0, 198, 195, 187, 220, 104, 225, 107, 197, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 74, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 76, 111, 99, 97, 116, 101, 100, 84, 101, 120, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 118, 97, 108, 117, 101, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e75816b56529d464 = b_e75816b56529d464.words; #if !CAPNP_LITE static const uint16_t m_e75816b56529d464[] = {2, 1, 0}; static const uint16_t i_e75816b56529d464[] = {0, 1, 2}; const ::capnp::_::RawSchema s_e75816b56529d464 = { 0xe75816b56529d464, b_e75816b56529d464.words, 66, nullptr, m_e75816b56529d464, 0, 3, i_e75816b56529d464, nullptr, nullptr, { &s_e75816b56529d464, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<66> b_991c7a3693d62cf2 = { { 0, 0, 0, 0, 5, 0, 6, 0, 242, 44, 214, 147, 54, 122, 28, 153, 29, 0, 0, 0, 1, 0, 2, 0, 198, 195, 187, 220, 104, 225, 107, 197, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 98, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 76, 111, 99, 97, 116, 101, 100, 73, 110, 116, 101, 103, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 118, 97, 108, 117, 101, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_991c7a3693d62cf2 = b_991c7a3693d62cf2.words; #if !CAPNP_LITE static const uint16_t m_991c7a3693d62cf2[] = {2, 1, 0}; static const uint16_t i_991c7a3693d62cf2[] = {0, 1, 2}; const ::capnp::_::RawSchema s_991c7a3693d62cf2 = { 0x991c7a3693d62cf2, b_991c7a3693d62cf2.words, 66, nullptr, m_991c7a3693d62cf2, 0, 3, i_991c7a3693d62cf2, nullptr, nullptr, { &s_991c7a3693d62cf2, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<66> b_90f2a60678fd2367 = { { 0, 0, 0, 0, 5, 0, 6, 0, 103, 35, 253, 120, 6, 166, 242, 144, 29, 0, 0, 0, 1, 0, 2, 0, 198, 195, 187, 220, 104, 225, 107, 197, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 82, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 76, 111, 99, 97, 116, 101, 100, 70, 108, 111, 97, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 118, 97, 108, 117, 101, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_90f2a60678fd2367 = b_90f2a60678fd2367.words; #if !CAPNP_LITE static const uint16_t m_90f2a60678fd2367[] = {2, 1, 0}; static const uint16_t i_90f2a60678fd2367[] = {0, 1, 2}; const ::capnp::_::RawSchema s_90f2a60678fd2367 = { 0x90f2a60678fd2367, b_90f2a60678fd2367.words, 66, nullptr, m_90f2a60678fd2367, 0, 3, i_90f2a60678fd2367, nullptr, nullptr, { &s_90f2a60678fd2367, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<262> b_8e207d4dfe54d0de = { { 0, 0, 0, 0, 5, 0, 6, 0, 222, 208, 84, 254, 77, 125, 32, 142, 29, 0, 0, 0, 1, 0, 3, 0, 198, 195, 187, 220, 104, 225, 107, 197, 2, 0, 7, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 66, 1, 0, 0, 37, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 135, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 69, 120, 112, 114, 101, 115, 115, 105, 111, 110, 0, 4, 0, 0, 0, 1, 0, 1, 0, 170, 219, 222, 26, 183, 70, 2, 201, 1, 0, 0, 0, 50, 0, 0, 0, 80, 97, 114, 97, 109, 0, 0, 0, 64, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 1, 0, 0, 3, 0, 1, 0, 184, 1, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 1, 0, 0, 3, 0, 1, 0, 192, 1, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 1, 0, 0, 3, 0, 1, 0, 200, 1, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 1, 0, 0, 3, 0, 1, 0, 204, 1, 0, 0, 2, 0, 1, 0, 4, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 1, 0, 0, 3, 0, 1, 0, 208, 1, 0, 0, 2, 0, 1, 0, 6, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 1, 0, 0, 3, 0, 1, 0, 216, 1, 0, 0, 2, 0, 1, 0, 10, 0, 249, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 1, 0, 0, 3, 0, 1, 0, 236, 1, 0, 0, 2, 0, 1, 0, 11, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 1, 0, 0, 3, 0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 0, 14, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 1, 0, 0, 3, 0, 1, 0, 8, 2, 0, 0, 2, 0, 1, 0, 15, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 1, 0, 12, 2, 0, 0, 2, 0, 1, 0, 5, 0, 247, 255, 0, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 3, 0, 1, 0, 16, 2, 0, 0, 2, 0, 1, 0, 12, 0, 246, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 122, 223, 176, 64, 112, 57, 232, 174, 13, 2, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 245, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 89, 51, 121, 13, 64, 225, 40, 170, 249, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 244, 255, 0, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 1, 0, 0, 3, 0, 1, 0, 236, 1, 0, 0, 2, 0, 1, 0, 8, 0, 243, 255, 0, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 1, 0, 0, 3, 0, 1, 0, 240, 1, 0, 0, 2, 0, 1, 0, 9, 0, 242, 255, 0, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 1, 0, 0, 3, 0, 1, 0, 244, 1, 0, 0, 2, 0, 1, 0, 117, 110, 107, 110, 111, 119, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 111, 115, 105, 116, 105, 118, 101, 73, 110, 116, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 101, 103, 97, 116, 105, 118, 101, 73, 110, 116, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 105, 110, 103, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 108, 97, 116, 105, 118, 101, 78, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 105, 115, 116, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 117, 112, 108, 101, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 170, 219, 222, 26, 183, 70, 2, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 105, 110, 97, 114, 121, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 109, 101, 109, 98, 101, 114, 0, 0, 97, 98, 115, 111, 108, 117, 116, 101, 78, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 109, 112, 111, 114, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 109, 98, 101, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_8e207d4dfe54d0de = b_8e207d4dfe54d0de.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_8e207d4dfe54d0de[] = { &s_8e207d4dfe54d0de, &s_aa28e1400d793359, &s_aee8397040b0df7a, &s_c90246b71adedbaa, &s_e75816b56529d464, }; static const uint16_t m_8e207d4dfe54d0de[] = {13, 11, 10, 15, 9, 3, 14, 6, 12, 2, 1, 5, 8, 4, 7, 0}; static const uint16_t i_8e207d4dfe54d0de[] = {0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8, 9}; const ::capnp::_::RawSchema s_8e207d4dfe54d0de = { 0x8e207d4dfe54d0de, b_8e207d4dfe54d0de.words, 262, d_8e207d4dfe54d0de, m_8e207d4dfe54d0de, 5, 16, i_8e207d4dfe54d0de, nullptr, nullptr, { &s_8e207d4dfe54d0de, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<65> b_c90246b71adedbaa = { { 0, 0, 0, 0, 5, 0, 6, 0, 170, 219, 222, 26, 183, 70, 2, 201, 40, 0, 0, 0, 1, 0, 1, 0, 222, 208, 84, 254, 77, 125, 32, 142, 2, 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 114, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 69, 120, 112, 114, 101, 115, 115, 105, 111, 110, 46, 80, 97, 114, 97, 109, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 117, 110, 110, 97, 109, 101, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 109, 101, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c90246b71adedbaa = b_c90246b71adedbaa.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c90246b71adedbaa[] = { &s_8e207d4dfe54d0de, &s_e75816b56529d464, }; static const uint16_t m_c90246b71adedbaa[] = {1, 0, 2}; static const uint16_t i_c90246b71adedbaa[] = {0, 1, 2}; const ::capnp::_::RawSchema s_c90246b71adedbaa = { 0xc90246b71adedbaa, b_c90246b71adedbaa.words, 65, d_c90246b71adedbaa, m_c90246b71adedbaa, 2, 3, i_c90246b71adedbaa, nullptr, nullptr, { &s_c90246b71adedbaa, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<55> b_aee8397040b0df7a = { { 0, 0, 0, 0, 5, 0, 6, 0, 122, 223, 176, 64, 112, 57, 232, 174, 40, 0, 0, 0, 1, 0, 3, 0, 222, 208, 84, 254, 77, 125, 32, 142, 2, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 162, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 69, 120, 112, 114, 101, 115, 115, 105, 111, 110, 46, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 72, 0, 0, 0, 2, 0, 1, 0, 102, 117, 110, 99, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 170, 219, 222, 26, 183, 70, 2, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_aee8397040b0df7a = b_aee8397040b0df7a.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_aee8397040b0df7a[] = { &s_8e207d4dfe54d0de, &s_c90246b71adedbaa, }; static const uint16_t m_aee8397040b0df7a[] = {0, 1}; static const uint16_t i_aee8397040b0df7a[] = {0, 1}; const ::capnp::_::RawSchema s_aee8397040b0df7a = { 0xaee8397040b0df7a, b_aee8397040b0df7a.words, 55, d_aee8397040b0df7a, m_aee8397040b0df7a, 2, 2, i_aee8397040b0df7a, nullptr, nullptr, { &s_aee8397040b0df7a, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_aa28e1400d793359 = { { 0, 0, 0, 0, 5, 0, 6, 0, 89, 51, 121, 13, 64, 225, 40, 170, 40, 0, 0, 0, 1, 0, 3, 0, 222, 208, 84, 254, 77, 125, 32, 142, 2, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 122, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 69, 120, 112, 114, 101, 115, 115, 105, 111, 110, 46, 109, 101, 109, 98, 101, 114, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 112, 97, 114, 101, 110, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_aa28e1400d793359 = b_aa28e1400d793359.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_aa28e1400d793359[] = { &s_8e207d4dfe54d0de, &s_e75816b56529d464, }; static const uint16_t m_aa28e1400d793359[] = {1, 0}; static const uint16_t i_aa28e1400d793359[] = {0, 1}; const ::capnp::_::RawSchema s_aa28e1400d793359 = { 0xaa28e1400d793359, b_aa28e1400d793359.words, 49, d_aa28e1400d793359, m_aa28e1400d793359, 2, 2, i_aa28e1400d793359, nullptr, nullptr, { &s_aa28e1400d793359, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<677> b_96efe787c17e83bb = { { 0, 0, 0, 0, 5, 0, 6, 0, 187, 131, 126, 193, 135, 231, 239, 150, 29, 0, 0, 0, 1, 0, 2, 0, 198, 195, 187, 220, 104, 225, 107, 197, 8, 0, 7, 0, 0, 0, 34, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 74, 1, 0, 0, 41, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 55, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 1, 0, 1, 0, 117, 225, 28, 175, 68, 17, 231, 213, 33, 0, 0, 0, 122, 0, 0, 0, 144, 98, 130, 115, 212, 137, 4, 208, 33, 0, 0, 0, 178, 0, 0, 0, 107, 45, 179, 158, 63, 156, 9, 148, 37, 0, 0, 0, 114, 0, 0, 0, 205, 27, 216, 121, 122, 110, 246, 179, 37, 0, 0, 0, 82, 0, 0, 0, 165, 210, 151, 166, 169, 8, 254, 255, 37, 0, 0, 0, 50, 0, 0, 0, 66, 114, 97, 110, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 80, 97, 114, 97, 109, 115, 0, 0, 0, 80, 97, 114, 97, 109, 76, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 80, 97, 114, 97, 109, 0, 0, 0, 168, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 4, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 4, 0, 0, 3, 0, 1, 0, 144, 4, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 150, 174, 3, 193, 115, 201, 240, 137, 141, 4, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 4, 0, 0, 3, 0, 1, 0, 144, 4, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 4, 0, 0, 3, 0, 1, 0, 168, 4, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 4, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 4, 0, 0, 3, 0, 1, 0, 176, 4, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 4, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 4, 0, 0, 3, 0, 1, 0, 180, 4, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 4, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 4, 0, 0, 3, 0, 1, 0, 188, 4, 0, 0, 2, 0, 1, 0, 8, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 4, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 4, 0, 0, 3, 0, 1, 0, 192, 4, 0, 0, 2, 0, 1, 0, 9, 0, 254, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 207, 44, 254, 11, 168, 100, 49, 233, 189, 4, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 253, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 12, 13, 207, 141, 42, 50, 72, 179, 165, 4, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 4, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 4, 0, 0, 3, 0, 1, 0, 148, 4, 0, 0, 2, 0, 1, 0, 12, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 4, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 4, 0, 0, 3, 0, 1, 0, 156, 4, 0, 0, 2, 0, 1, 0, 13, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 4, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 4, 0, 0, 3, 0, 1, 0, 160, 4, 0, 0, 2, 0, 1, 0, 14, 0, 249, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 200, 88, 179, 143, 32, 34, 38, 143, 157, 4, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 4, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 4, 0, 0, 3, 0, 1, 0, 140, 4, 0, 0, 2, 0, 1, 0, 16, 0, 247, 255, 0, 0, 0, 0, 0, 0, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 4, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 4, 0, 0, 3, 0, 1, 0, 144, 4, 0, 0, 2, 0, 1, 0, 17, 0, 246, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 211, 53, 2, 243, 234, 144, 42, 153, 141, 4, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 245, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 185, 192, 23, 214, 71, 24, 151, 235, 121, 4, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 244, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 127, 3, 152, 49, 110, 232, 185, 156, 97, 4, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 243, 255, 5, 0, 0, 0, 0, 0, 1, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 4, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 4, 0, 0, 3, 0, 1, 0, 84, 4, 0, 0, 2, 0, 1, 0, 21, 0, 242, 255, 5, 0, 0, 0, 0, 0, 1, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 4, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 4, 0, 0, 3, 0, 1, 0, 92, 4, 0, 0, 2, 0, 1, 0, 22, 0, 241, 255, 0, 0, 0, 0, 0, 0, 1, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 4, 0, 0, 3, 0, 1, 0, 100, 4, 0, 0, 2, 0, 1, 0, 23, 0, 240, 255, 0, 0, 0, 0, 0, 0, 1, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 4, 0, 0, 3, 0, 1, 0, 108, 4, 0, 0, 2, 0, 1, 0, 24, 0, 239, 255, 0, 0, 0, 0, 0, 0, 1, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 4, 0, 0, 3, 0, 1, 0, 116, 4, 0, 0, 2, 0, 1, 0, 25, 0, 238, 255, 0, 0, 0, 0, 0, 0, 1, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 4, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 4, 0, 0, 3, 0, 1, 0, 124, 4, 0, 0, 2, 0, 1, 0, 26, 0, 237, 255, 0, 0, 0, 0, 0, 0, 1, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 4, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 4, 0, 0, 3, 0, 1, 0, 132, 4, 0, 0, 2, 0, 1, 0, 27, 0, 236, 255, 0, 0, 0, 0, 0, 0, 1, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 4, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 4, 0, 0, 3, 0, 1, 0, 140, 4, 0, 0, 2, 0, 1, 0, 28, 0, 235, 255, 0, 0, 0, 0, 0, 0, 1, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 4, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 4, 0, 0, 3, 0, 1, 0, 148, 4, 0, 0, 2, 0, 1, 0, 29, 0, 234, 255, 0, 0, 0, 0, 0, 0, 1, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 4, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 4, 0, 0, 3, 0, 1, 0, 156, 4, 0, 0, 2, 0, 1, 0, 30, 0, 233, 255, 0, 0, 0, 0, 0, 0, 1, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 4, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 4, 0, 0, 3, 0, 1, 0, 164, 4, 0, 0, 2, 0, 1, 0, 31, 0, 232, 255, 0, 0, 0, 0, 0, 0, 1, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 4, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 4, 0, 0, 3, 0, 1, 0, 172, 4, 0, 0, 2, 0, 1, 0, 32, 0, 231, 255, 0, 0, 0, 0, 0, 0, 1, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 4, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 4, 0, 0, 3, 0, 1, 0, 180, 4, 0, 0, 2, 0, 1, 0, 33, 0, 230, 255, 0, 0, 0, 0, 0, 0, 1, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 4, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 4, 0, 0, 3, 0, 1, 0, 188, 4, 0, 0, 2, 0, 1, 0, 34, 0, 229, 255, 0, 0, 0, 0, 0, 0, 1, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 4, 0, 0, 3, 0, 1, 0, 196, 4, 0, 0, 2, 0, 1, 0, 35, 0, 228, 255, 0, 0, 0, 0, 0, 0, 1, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 4, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 4, 0, 0, 3, 0, 1, 0, 204, 4, 0, 0, 2, 0, 1, 0, 36, 0, 227, 255, 0, 0, 0, 0, 0, 0, 1, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 4, 0, 0, 98, 0, 0, 0, 205, 4, 0, 0, 31, 0, 0, 0, 248, 4, 0, 0, 3, 0, 1, 0, 4, 5, 0, 0, 2, 0, 1, 0, 37, 0, 226, 255, 0, 0, 0, 0, 0, 0, 1, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 3, 0, 1, 0, 12, 5, 0, 0, 2, 0, 1, 0, 38, 0, 225, 255, 0, 0, 0, 0, 0, 0, 1, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 5, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 5, 0, 0, 3, 0, 1, 0, 24, 5, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 5, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 5, 0, 0, 3, 0, 1, 0, 48, 5, 0, 0, 2, 0, 1, 0, 39, 0, 224, 255, 0, 0, 0, 0, 0, 0, 1, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 5, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 5, 0, 0, 3, 0, 1, 0, 60, 5, 0, 0, 2, 0, 1, 0, 40, 0, 223, 255, 0, 0, 0, 0, 0, 0, 1, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 5, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 5, 0, 0, 3, 0, 1, 0, 68, 5, 0, 0, 2, 0, 1, 0, 41, 0, 222, 255, 0, 0, 0, 0, 0, 0, 1, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 5, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 5, 0, 0, 3, 0, 1, 0, 80, 5, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 100, 0, 0, 0, 0, 0, 0, 110, 101, 115, 116, 101, 100, 68, 101, 99, 108, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 187, 131, 126, 193, 135, 231, 239, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 144, 98, 130, 115, 212, 137, 4, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 111, 99, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 115, 105, 110, 103, 0, 0, 0, 99, 111, 110, 115, 116, 0, 0, 0, 101, 110, 117, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 117, 109, 101, 114, 97, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 117, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 101, 108, 100, 0, 0, 0, 117, 110, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 114, 111, 117, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 109, 101, 116, 104, 111, 100, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 110, 97, 107, 101, 100, 73, 100, 0, 16, 0, 0, 0, 0, 0, 0, 0, 242, 44, 214, 147, 54, 122, 28, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 107, 101, 100, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 16, 0, 0, 0, 0, 0, 0, 0, 144, 98, 130, 115, 212, 137, 4, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 86, 111, 105, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 66, 111, 111, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 73, 110, 116, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 73, 110, 116, 49, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 73, 110, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 73, 110, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 85, 73, 110, 116, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 85, 73, 110, 116, 49, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 85, 73, 110, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 85, 73, 110, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 70, 108, 111, 97, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 70, 108, 111, 97, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 84, 101, 120, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 68, 97, 116, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 76, 105, 115, 116, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 2, 0, 107, 45, 179, 158, 63, 156, 9, 148, 4, 0, 0, 0, 2, 0, 1, 0, 28, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 66, 0, 0, 0, 69, 108, 101, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 79, 98, 106, 101, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 65, 110, 121, 80, 111, 105, 110, 116, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 117, 225, 28, 175, 68, 17, 231, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 65, 110, 121, 83, 116, 114, 117, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 65, 110, 121, 76, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 105, 108, 116, 105, 110, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_96efe787c17e83bb = b_96efe787c17e83bb.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_96efe787c17e83bb[] = { &s_89f0c973c103ae96, &s_8f2622208fb358c8, &s_96efe787c17e83bb, &s_991c7a3693d62cf2, &s_992a90eaf30235d3, &s_9cb9e86e3198037f, &s_b348322a8dcf0d0c, &s_d00489d473826290, &s_d5e71144af1ce175, &s_e75816b56529d464, &s_e93164a80bfe2ccf, &s_eb971847d617c0b9, }; static const uint16_t m_96efe787c17e83bb[] = {18, 3, 40, 37, 39, 22, 41, 34, 31, 32, 24, 25, 26, 23, 35, 36, 33, 28, 29, 30, 27, 21, 9, 6, 5, 10, 11, 13, 7, 15, 1, 16, 17, 20, 19, 0, 2, 38, 4, 12, 14, 8}; static const uint16_t i_96efe787c17e83bb[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 0, 1, 2, 3, 4, 5, 6, 38}; const ::capnp::_::RawSchema s_96efe787c17e83bb = { 0x96efe787c17e83bb, b_96efe787c17e83bb.words, 677, d_96efe787c17e83bb, m_96efe787c17e83bb, 12, 42, i_96efe787c17e83bb, nullptr, nullptr, { &s_96efe787c17e83bb, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<67> b_d5e71144af1ce175 = { { 0, 0, 0, 0, 5, 0, 6, 0, 117, 225, 28, 175, 68, 17, 231, 213, 41, 0, 0, 0, 1, 0, 1, 0, 187, 131, 126, 193, 135, 231, 239, 150, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 1, 0, 0, 45, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 66, 114, 97, 110, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d5e71144af1ce175 = b_d5e71144af1ce175.words; #if !CAPNP_LITE static const uint16_t m_d5e71144af1ce175[] = {2, 0, 1}; static const uint16_t i_d5e71144af1ce175[] = {0, 1, 2}; const ::capnp::_::RawSchema s_d5e71144af1ce175 = { 0xd5e71144af1ce175, b_d5e71144af1ce175.words, 67, nullptr, m_d5e71144af1ce175, 0, 3, i_d5e71144af1ce175, nullptr, nullptr, { &s_d5e71144af1ce175, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<45> b_d00489d473826290 = { { 0, 0, 0, 0, 5, 0, 6, 0, 144, 98, 130, 115, 212, 137, 4, 208, 41, 0, 0, 0, 1, 0, 1, 0, 187, 131, 126, 193, 135, 231, 239, 150, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 1, 0, 0, 49, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 249, 106, 223, 92, 217, 238, 90, 251, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, } }; ::capnp::word const* const bp_d00489d473826290 = b_d00489d473826290.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d00489d473826290[] = { &s_8e207d4dfe54d0de, &s_fb5aeed95cdf6af9, }; static const uint16_t m_d00489d473826290[] = {0, 1}; static const uint16_t i_d00489d473826290[] = {0, 1}; const ::capnp::_::RawSchema s_d00489d473826290 = { 0xd00489d473826290, b_d00489d473826290.words, 45, d_d00489d473826290, m_d00489d473826290, 2, 2, i_d00489d473826290, nullptr, nullptr, { &s_d00489d473826290, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<53> b_fb5aeed95cdf6af9 = { { 0, 0, 0, 0, 5, 0, 6, 0, 249, 106, 223, 92, 217, 238, 90, 251, 63, 0, 0, 0, 1, 0, 1, 0, 144, 98, 130, 115, 212, 137, 4, 208, 2, 0, 7, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 46, 118, 97, 108, 117, 101, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 110, 111, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 120, 112, 114, 101, 115, 115, 105, 111, 110, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_fb5aeed95cdf6af9 = b_fb5aeed95cdf6af9.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_fb5aeed95cdf6af9[] = { &s_8e207d4dfe54d0de, &s_d00489d473826290, }; static const uint16_t m_fb5aeed95cdf6af9[] = {1, 0}; static const uint16_t i_fb5aeed95cdf6af9[] = {0, 1}; const ::capnp::_::RawSchema s_fb5aeed95cdf6af9 = { 0xfb5aeed95cdf6af9, b_fb5aeed95cdf6af9.words, 53, d_fb5aeed95cdf6af9, m_fb5aeed95cdf6af9, 2, 2, i_fb5aeed95cdf6af9, nullptr, nullptr, { &s_fb5aeed95cdf6af9, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<28> b_94099c3f9eb32d6b = { { 0, 0, 0, 0, 5, 0, 6, 0, 107, 45, 179, 158, 63, 156, 9, 148, 41, 0, 0, 0, 5, 0, 32, 0, 187, 131, 126, 193, 135, 231, 239, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 1, 0, 0, 45, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 98, 117, 105, 108, 116, 105, 110, 80, 97, 114, 97, 109, 115, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 117, 225, 28, 175, 68, 17, 231, 213, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_94099c3f9eb32d6b = b_94099c3f9eb32d6b.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_94099c3f9eb32d6b = { 0x94099c3f9eb32d6b, b_94099c3f9eb32d6b.words, 28, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_94099c3f9eb32d6b, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<102> b_b3f66e7a79d81bcd = { { 0, 0, 0, 0, 5, 0, 6, 0, 205, 27, 216, 121, 122, 110, 246, 179, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 1, 0, 7, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 154, 1, 0, 0, 45, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 80, 97, 114, 97, 109, 76, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 20, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 3, 0, 1, 0, 152, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 3, 0, 1, 0, 156, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 3, 0, 1, 0, 164, 0, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 3, 0, 1, 0, 168, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 3, 0, 1, 0, 172, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 100, 76, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 165, 210, 151, 166, 169, 8, 254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 101, 97, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b3f66e7a79d81bcd = b_b3f66e7a79d81bcd.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_b3f66e7a79d81bcd[] = { &s_8e207d4dfe54d0de, &s_fffe08a9a697d2a5, }; static const uint16_t m_b3f66e7a79d81bcd[] = {3, 0, 2, 4, 1}; static const uint16_t i_b3f66e7a79d81bcd[] = {0, 1, 4, 2, 3}; const ::capnp::_::RawSchema s_b3f66e7a79d81bcd = { 0xb3f66e7a79d81bcd, b_b3f66e7a79d81bcd.words, 102, d_b3f66e7a79d81bcd, m_b3f66e7a79d81bcd, 2, 5, i_b3f66e7a79d81bcd, nullptr, nullptr, { &s_b3f66e7a79d81bcd, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<110> b_fffe08a9a697d2a5 = { { 0, 0, 0, 0, 5, 0, 6, 0, 165, 210, 151, 166, 169, 8, 254, 255, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 122, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 87, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 80, 97, 114, 97, 109, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 24, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 3, 0, 1, 0, 160, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 3, 0, 1, 0, 164, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 3, 0, 1, 0, 188, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 71, 234, 136, 253, 21, 69, 16, 229, 185, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, 0, 3, 0, 1, 0, 176, 0, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 3, 0, 1, 0, 180, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 100, 212, 41, 101, 181, 22, 88, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 144, 98, 130, 115, 212, 137, 4, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_fffe08a9a697d2a5 = b_fffe08a9a697d2a5.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_fffe08a9a697d2a5[] = { &s_8e207d4dfe54d0de, &s_d00489d473826290, &s_e5104515fd88ea47, &s_e75816b56529d464, }; static const uint16_t m_fffe08a9a697d2a5[] = {2, 3, 5, 0, 4, 1}; static const uint16_t i_fffe08a9a697d2a5[] = {0, 1, 2, 3, 4, 5}; const ::capnp::_::RawSchema s_fffe08a9a697d2a5 = { 0xfffe08a9a697d2a5, b_fffe08a9a697d2a5.words, 110, d_fffe08a9a697d2a5, m_fffe08a9a697d2a5, 4, 6, i_fffe08a9a697d2a5, nullptr, nullptr, { &s_fffe08a9a697d2a5, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_e5104515fd88ea47 = { { 0, 0, 0, 0, 5, 0, 6, 0, 71, 234, 136, 253, 21, 69, 16, 229, 47, 0, 0, 0, 1, 0, 2, 0, 165, 210, 151, 166, 169, 8, 254, 255, 4, 0, 7, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 80, 97, 114, 97, 109, 46, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 3, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 110, 111, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e5104515fd88ea47 = b_e5104515fd88ea47.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_e5104515fd88ea47[] = { &s_8e207d4dfe54d0de, &s_fffe08a9a697d2a5, }; static const uint16_t m_e5104515fd88ea47[] = {0, 1}; static const uint16_t i_e5104515fd88ea47[] = {0, 1}; const ::capnp::_::RawSchema s_e5104515fd88ea47 = { 0xe5104515fd88ea47, b_e5104515fd88ea47.words, 51, d_e5104515fd88ea47, m_e5104515fd88ea47, 2, 2, i_e5104515fd88ea47, nullptr, nullptr, { &s_e5104515fd88ea47, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<65> b_89f0c973c103ae96 = { { 0, 0, 0, 0, 5, 0, 6, 0, 150, 174, 3, 193, 115, 201, 240, 137, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 98, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 105, 100, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 117, 110, 115, 112, 101, 99, 105, 102, 105, 101, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 100, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 242, 44, 214, 147, 54, 122, 28, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 114, 100, 105, 110, 97, 108, 0, 16, 0, 0, 0, 0, 0, 0, 0, 242, 44, 214, 147, 54, 122, 28, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_89f0c973c103ae96 = b_89f0c973c103ae96.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_89f0c973c103ae96[] = { &s_96efe787c17e83bb, &s_991c7a3693d62cf2, }; static const uint16_t m_89f0c973c103ae96[] = {2, 1, 0}; static const uint16_t i_89f0c973c103ae96[] = {0, 1, 2}; const ::capnp::_::RawSchema s_89f0c973c103ae96 = { 0x89f0c973c103ae96, b_89f0c973c103ae96.words, 65, d_89f0c973c103ae96, m_89f0c973c103ae96, 2, 3, i_89f0c973c103ae96, nullptr, nullptr, { &s_89f0c973c103ae96, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<34> b_e93164a80bfe2ccf = { { 0, 0, 0, 0, 5, 0, 6, 0, 207, 44, 254, 11, 168, 100, 49, 233, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 122, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 117, 115, 105, 110, 103, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 116, 97, 114, 103, 101, 116, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e93164a80bfe2ccf = b_e93164a80bfe2ccf.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_e93164a80bfe2ccf[] = { &s_8e207d4dfe54d0de, &s_96efe787c17e83bb, }; static const uint16_t m_e93164a80bfe2ccf[] = {0}; static const uint16_t i_e93164a80bfe2ccf[] = {0}; const ::capnp::_::RawSchema s_e93164a80bfe2ccf = { 0xe93164a80bfe2ccf, b_e93164a80bfe2ccf.words, 34, d_e93164a80bfe2ccf, m_e93164a80bfe2ccf, 2, 1, i_e93164a80bfe2ccf, nullptr, nullptr, { &s_e93164a80bfe2ccf, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_b348322a8dcf0d0c = { { 0, 0, 0, 0, 5, 0, 6, 0, 12, 13, 207, 141, 42, 50, 72, 179, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 122, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 99, 111, 110, 115, 116, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b348322a8dcf0d0c = b_b348322a8dcf0d0c.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_b348322a8dcf0d0c[] = { &s_8e207d4dfe54d0de, &s_96efe787c17e83bb, }; static const uint16_t m_b348322a8dcf0d0c[] = {0, 1}; static const uint16_t i_b348322a8dcf0d0c[] = {0, 1}; const ::capnp::_::RawSchema s_b348322a8dcf0d0c = { 0xb348322a8dcf0d0c, b_b348322a8dcf0d0c.words, 49, d_b348322a8dcf0d0c, m_b348322a8dcf0d0c, 2, 2, i_b348322a8dcf0d0c, nullptr, nullptr, { &s_b348322a8dcf0d0c, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<43> b_8f2622208fb358c8 = { { 0, 0, 0, 0, 5, 0, 6, 0, 200, 88, 179, 143, 32, 34, 38, 143, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 122, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 102, 105, 101, 108, 100, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 31, 149, 23, 230, 29, 162, 209, 208, 45, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, } }; ::capnp::word const* const bp_8f2622208fb358c8 = b_8f2622208fb358c8.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_8f2622208fb358c8[] = { &s_8e207d4dfe54d0de, &s_96efe787c17e83bb, &s_d0d1a21de617951f, }; static const uint16_t m_8f2622208fb358c8[] = {1, 0}; static const uint16_t i_8f2622208fb358c8[] = {0, 1}; const ::capnp::_::RawSchema s_8f2622208fb358c8 = { 0x8f2622208fb358c8, b_8f2622208fb358c8.words, 43, d_8f2622208fb358c8, m_8f2622208fb358c8, 3, 2, i_8f2622208fb358c8, nullptr, nullptr, { &s_8f2622208fb358c8, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_d0d1a21de617951f = { { 0, 0, 0, 0, 5, 0, 6, 0, 31, 149, 23, 230, 29, 162, 209, 208, 47, 0, 0, 0, 1, 0, 2, 0, 200, 88, 179, 143, 32, 34, 38, 143, 8, 0, 7, 0, 1, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 102, 105, 101, 108, 100, 46, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 6, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 110, 111, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d0d1a21de617951f = b_d0d1a21de617951f.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d0d1a21de617951f[] = { &s_8e207d4dfe54d0de, &s_8f2622208fb358c8, }; static const uint16_t m_d0d1a21de617951f[] = {0, 1}; static const uint16_t i_d0d1a21de617951f[] = {0, 1}; const ::capnp::_::RawSchema s_d0d1a21de617951f = { 0xd0d1a21de617951f, b_d0d1a21de617951f.words, 51, d_d0d1a21de617951f, m_d0d1a21de617951f, 2, 2, i_d0d1a21de617951f, nullptr, nullptr, { &s_d0d1a21de617951f, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<40> b_992a90eaf30235d3 = { { 0, 0, 0, 0, 5, 0, 6, 0, 211, 53, 2, 243, 234, 144, 42, 153, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 154, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 40, 0, 0, 0, 2, 0, 1, 0, 115, 117, 112, 101, 114, 99, 108, 97, 115, 115, 101, 115, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_992a90eaf30235d3 = b_992a90eaf30235d3.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_992a90eaf30235d3[] = { &s_8e207d4dfe54d0de, &s_96efe787c17e83bb, }; static const uint16_t m_992a90eaf30235d3[] = {0}; static const uint16_t i_992a90eaf30235d3[] = {0}; const ::capnp::_::RawSchema s_992a90eaf30235d3 = { 0x992a90eaf30235d3, b_992a90eaf30235d3.words, 40, d_992a90eaf30235d3, m_992a90eaf30235d3, 2, 1, i_992a90eaf30235d3, nullptr, nullptr, { &s_992a90eaf30235d3, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<42> b_eb971847d617c0b9 = { { 0, 0, 0, 0, 5, 0, 6, 0, 185, 192, 23, 214, 71, 24, 151, 235, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 130, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 109, 101, 116, 104, 111, 100, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 115, 81, 214, 98, 125, 140, 35, 198, 45, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 115, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 205, 27, 216, 121, 122, 110, 246, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 117, 108, 116, 115, 0, } }; ::capnp::word const* const bp_eb971847d617c0b9 = b_eb971847d617c0b9.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_eb971847d617c0b9[] = { &s_96efe787c17e83bb, &s_b3f66e7a79d81bcd, &s_c6238c7d62d65173, }; static const uint16_t m_eb971847d617c0b9[] = {0, 1}; static const uint16_t i_eb971847d617c0b9[] = {0, 1}; const ::capnp::_::RawSchema s_eb971847d617c0b9 = { 0xeb971847d617c0b9, b_eb971847d617c0b9.words, 42, d_eb971847d617c0b9, m_eb971847d617c0b9, 3, 2, i_eb971847d617c0b9, nullptr, nullptr, { &s_eb971847d617c0b9, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_c6238c7d62d65173 = { { 0, 0, 0, 0, 5, 0, 6, 0, 115, 81, 214, 98, 125, 140, 35, 198, 48, 0, 0, 0, 1, 0, 2, 0, 185, 192, 23, 214, 71, 24, 151, 235, 8, 0, 7, 0, 1, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 109, 101, 116, 104, 111, 100, 46, 114, 101, 115, 117, 108, 116, 115, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 6, 0, 0, 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 110, 111, 110, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 120, 112, 108, 105, 99, 105, 116, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 205, 27, 216, 121, 122, 110, 246, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c6238c7d62d65173 = b_c6238c7d62d65173.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c6238c7d62d65173[] = { &s_b3f66e7a79d81bcd, &s_eb971847d617c0b9, }; static const uint16_t m_c6238c7d62d65173[] = {1, 0}; static const uint16_t i_c6238c7d62d65173[] = {0, 1}; const ::capnp::_::RawSchema s_c6238c7d62d65173 = { 0xc6238c7d62d65173, b_c6238c7d62d65173.words, 51, d_c6238c7d62d65173, m_c6238c7d62d65173, 2, 2, i_c6238c7d62d65173, nullptr, nullptr, { &s_c6238c7d62d65173, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<230> b_9cb9e86e3198037f = { { 0, 0, 0, 0, 5, 0, 6, 0, 127, 3, 152, 49, 110, 232, 185, 156, 41, 0, 0, 0, 1, 0, 2, 0, 187, 131, 126, 193, 135, 231, 239, 150, 8, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 162, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 223, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 68, 101, 99, 108, 97, 114, 97, 116, 105, 111, 110, 46, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 52, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 1, 0, 0, 3, 0, 1, 0, 100, 1, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 96, 0, 0, 0, 0, 0, 1, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 1, 0, 0, 3, 0, 1, 0, 108, 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 97, 0, 0, 0, 0, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 1, 0, 0, 3, 0, 1, 0, 116, 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 98, 0, 0, 0, 0, 0, 1, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 1, 0, 0, 3, 0, 1, 0, 124, 1, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 99, 0, 0, 0, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 1, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 1, 0, 0, 3, 0, 1, 0, 136, 1, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 1, 0, 0, 3, 0, 1, 0, 144, 1, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 101, 0, 0, 0, 0, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 1, 0, 0, 3, 0, 1, 0, 152, 1, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 102, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 0, 0, 3, 0, 1, 0, 160, 1, 0, 0, 2, 0, 1, 0, 8, 0, 0, 0, 103, 0, 0, 0, 0, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 1, 0, 0, 3, 0, 1, 0, 168, 1, 0, 0, 2, 0, 1, 0, 9, 0, 0, 0, 104, 0, 0, 0, 0, 0, 1, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 1, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 3, 0, 1, 0, 180, 1, 0, 0, 2, 0, 1, 0, 10, 0, 0, 0, 105, 0, 0, 0, 0, 0, 1, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 1, 0, 0, 3, 0, 1, 0, 188, 1, 0, 0, 2, 0, 1, 0, 11, 0, 0, 0, 106, 0, 0, 0, 0, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 1, 0, 0, 3, 0, 1, 0, 196, 1, 0, 0, 2, 0, 1, 0, 12, 0, 0, 0, 107, 0, 0, 0, 0, 0, 1, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 1, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 1, 0, 0, 3, 0, 1, 0, 208, 1, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 222, 208, 84, 254, 77, 125, 32, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 70, 105, 108, 101, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 67, 111, 110, 115, 116, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 69, 110, 117, 109, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 69, 110, 117, 109, 101, 114, 97, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 83, 116, 114, 117, 99, 116, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 70, 105, 101, 108, 100, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 85, 110, 105, 111, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 71, 114, 111, 117, 112, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 73, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 77, 101, 116, 104, 111, 100, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 80, 97, 114, 97, 109, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9cb9e86e3198037f = b_9cb9e86e3198037f.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9cb9e86e3198037f[] = { &s_8e207d4dfe54d0de, &s_96efe787c17e83bb, }; static const uint16_t m_9cb9e86e3198037f[] = {12, 2, 3, 4, 6, 1, 8, 9, 10, 11, 5, 7, 0}; static const uint16_t i_9cb9e86e3198037f[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; const ::capnp::_::RawSchema s_9cb9e86e3198037f = { 0x9cb9e86e3198037f, b_9cb9e86e3198037f.words, 230, d_9cb9e86e3198037f, m_9cb9e86e3198037f, 2, 13, i_9cb9e86e3198037f, nullptr, nullptr, { &s_9cb9e86e3198037f, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<34> b_84e4f3f5a807605c = { { 0, 0, 0, 0, 5, 0, 6, 0, 92, 96, 7, 168, 245, 243, 228, 132, 29, 0, 0, 0, 1, 0, 0, 0, 198, 195, 187, 220, 104, 225, 107, 197, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 66, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 105, 108, 101, 114, 47, 103, 114, 97, 109, 109, 97, 114, 46, 99, 97, 112, 110, 112, 58, 80, 97, 114, 115, 101, 100, 70, 105, 108, 101, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 114, 111, 111, 116, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 187, 131, 126, 193, 135, 231, 239, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_84e4f3f5a807605c = b_84e4f3f5a807605c.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_84e4f3f5a807605c[] = { &s_96efe787c17e83bb, }; static const uint16_t m_84e4f3f5a807605c[] = {0}; static const uint16_t i_84e4f3f5a807605c[] = {0}; const ::capnp::_::RawSchema s_84e4f3f5a807605c = { 0x84e4f3f5a807605c, b_84e4f3f5a807605c.words, 34, d_84e4f3f5a807605c, m_84e4f3f5a807605c, 1, 1, i_84e4f3f5a807605c, nullptr, nullptr, { &s_84e4f3f5a807605c, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace compiler { // LocatedText #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t LocatedText::_capnpPrivate::dataWordSize; constexpr uint16_t LocatedText::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind LocatedText::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* LocatedText::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // LocatedInteger #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t LocatedInteger::_capnpPrivate::dataWordSize; constexpr uint16_t LocatedInteger::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind LocatedInteger::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* LocatedInteger::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // LocatedFloat #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t LocatedFloat::_capnpPrivate::dataWordSize; constexpr uint16_t LocatedFloat::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind LocatedFloat::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* LocatedFloat::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Expression #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Expression::_capnpPrivate::dataWordSize; constexpr uint16_t Expression::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Expression::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Expression::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Expression::Param #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Expression::Param::_capnpPrivate::dataWordSize; constexpr uint16_t Expression::Param::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Expression::Param::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Expression::Param::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Expression::Application #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Expression::Application::_capnpPrivate::dataWordSize; constexpr uint16_t Expression::Application::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Expression::Application::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Expression::Application::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Expression::Member #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Expression::Member::_capnpPrivate::dataWordSize; constexpr uint16_t Expression::Member::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Expression::Member::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Expression::Member::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::BrandParameter #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::BrandParameter::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::BrandParameter::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::BrandParameter::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::BrandParameter::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::AnnotationApplication #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::AnnotationApplication::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::AnnotationApplication::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::AnnotationApplication::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::AnnotationApplication::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::AnnotationApplication::Value #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::AnnotationApplication::Value::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::AnnotationApplication::Value::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::AnnotationApplication::Value::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::AnnotationApplication::Value::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::ParamList #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::ParamList::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::ParamList::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::ParamList::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::ParamList::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Param #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Param::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Param::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Param::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Param::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Param::DefaultValue #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Param::DefaultValue::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Param::DefaultValue::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Param::DefaultValue::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Param::DefaultValue::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Id #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Id::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Id::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Id::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Id::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Using #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Using::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Using::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Using::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Using::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Const #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Const::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Const::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Const::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Const::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Field #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Field::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Field::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Field::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Field::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Field::DefaultValue #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Field::DefaultValue::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Field::DefaultValue::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Field::DefaultValue::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Field::DefaultValue::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Interface #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Interface::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Interface::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Interface::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Interface::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Method #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Method::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Method::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Method::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Method::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Method::Results #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Method::Results::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Method::Results::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Method::Results::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Method::Results::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Declaration::Annotation #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Declaration::Annotation::_capnpPrivate::dataWordSize; constexpr uint16_t Declaration::Annotation::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Declaration::Annotation::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Declaration::Annotation::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // ParsedFile #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t ParsedFile::_capnpPrivate::dataWordSize; constexpr uint16_t ParsedFile::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind ParsedFile::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* ParsedFile::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/compiler/parser.h0000644000175000017500000001351114712011043022103 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include #include "error-reporter.h" CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { void parseFile(List::Reader statements, ParsedFile::Builder result, ErrorReporter& errorReporter, bool requiresId); // Parse a list of statements to build a ParsedFile. // // If any errors are reported, then the output is not usable. However, it may be passed on through // later stages of compilation in order to detect additional errors. uint64_t generateRandomId(); // Generate a new random unique ID. This lives here mostly for lack of a better location. uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName); // Generate the ID for a child node given its parent ID and name. uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex); // Generate the ID for a group within a struct. uint64_t generateMethodParamsId(uint64_t parentId, uint16_t methodOrdinal, bool isResults); // Generate the ID for a struct representing method params / results. // // TODO(cleanup): Move generate*Id() somewhere more sensible. class CapnpParser { // Advanced parser interface. This interface exposes the inner parsers so that you can embed // them into your own parsers. public: CapnpParser(Orphanage orphanage, ErrorReporter& errorReporter); // `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is // a pointer to the beginning of the input, used to compute byte offsets. ~CapnpParser() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(CapnpParser); using ParserInput = kj::parse::IteratorInput::Reader::Iterator>; struct DeclParserResult; template using Parser = kj::parse::ParserRef; using DeclParser = Parser; kj::Maybe> parseStatement( Statement::Reader statement, const DeclParser& parser); // Parse a statement using the given parser. In addition to parsing the token sequence itself, // this takes care of parsing the block (if any) and copying over the doc comment (if any). struct DeclParserResult { // DeclParser parses a sequence of tokens representing just the "line" part of the statement -- // i.e. everything up to the semicolon or opening curly brace. // // Use `parseStatement()` to avoid having to deal with this struct. Orphan decl; // The decl parsed so far. The decl's `docComment` and `nestedDecls` are both empty at this // point. kj::Maybe memberParser; // If null, the statement should not have a block. If non-null, the statement should have a // block containing statements parseable by this parser. DeclParserResult(Orphan&& decl, const DeclParser& memberParser) : decl(kj::mv(decl)), memberParser(memberParser) {} explicit DeclParserResult(Orphan&& decl) : decl(kj::mv(decl)), memberParser(nullptr) {} }; struct Parsers { DeclParser genericDecl; // Parser that matches any declaration type except those that have ordinals (since they are // context-dependent). DeclParser fileLevelDecl; DeclParser enumLevelDecl; DeclParser structLevelDecl; DeclParser interfaceLevelDecl; // Parsers that match genericDecl *and* the ordinal-based declaration types valid in the given // contexts. Note that these may match declarations that are not actually allowed in the given // contexts, as long as the grammar is unambiguous. E.g. nested types are not allowed in // enums, but they'll be accepted by enumLevelDecl. A later stage of compilation should report // these as errors. Parser> expression; Parser> annotation; Parser> uid; Parser> ordinal; Parser> param; DeclParser usingDecl; DeclParser constDecl; DeclParser enumDecl; DeclParser enumerantDecl; DeclParser structDecl; DeclParser fieldDecl; DeclParser unionDecl; DeclParser groupDecl; DeclParser interfaceDecl; DeclParser methodDecl; DeclParser paramDecl; DeclParser annotationDecl; // Parsers for individual declaration types. }; const Parsers& getParsers() { return parsers; } private: Orphanage orphanage; ErrorReporter& errorReporter; kj::Arena arena; Parsers parsers; }; kj::String expressionString(Expression::Reader name); // Stringify the expression as code. } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/capnp-test.sh0000755000175000017500000001735614527152321023077 0ustar00kentonkenton00000000000000#! /bin/sh # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # Tests the `capnp` tool's various commands, other than `compile`. set -eu fail() { echo "FAILED: $@" >&2 exit 1 } if test -f ./capnp; then CAPNP=${CAPNP:-./capnp} elif test -f ./capnp.exe; then CAPNP=${CAPNP:-./capnp.exe} else CAPNP=${CAPNP:-capnp} fi SCHEMA=`dirname "$0"`/../test.capnp JSON_SCHEMA=`dirname "$0"`/../compat/json-test.capnp TESTDATA=`dirname "$0"`/../testdata SRCDIR=`dirname "$0"`/../.. SUFFIX=${TESTDATA#*/src/} PREFIX=${TESTDATA%${SUFFIX}} if [ "$PREFIX" = "" ]; then PREFIX=. fi # ======================================================================================== # convert $CAPNP convert text:binary $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/binary - || fail encode $CAPNP convert text:flat $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/flat - || fail encode flat $CAPNP convert text:packed $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/packed - || fail encode packed $CAPNP convert text:flat-packed $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/packedflat - || fail encode packedflat $CAPNP convert text:binary $SCHEMA TestAllTypes < $TESTDATA/pretty.txt | cmp $TESTDATA/binary - || fail parse pretty $CAPNP convert binary:text $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/pretty.txt - || fail decode $CAPNP convert flat:text $SCHEMA TestAllTypes < $TESTDATA/flat | cmp $TESTDATA/pretty.txt - || fail decode flat $CAPNP convert packed:text $SCHEMA TestAllTypes < $TESTDATA/packed | cmp $TESTDATA/pretty.txt - || fail decode packed $CAPNP convert flat-packed:text $SCHEMA TestAllTypes < $TESTDATA/packedflat | cmp $TESTDATA/pretty.txt - || fail decode packedflat $CAPNP convert binary:text --short $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/short.txt - || fail decode short $CAPNP convert binary:text $SCHEMA TestAllTypes < $TESTDATA/segmented | cmp $TESTDATA/pretty.txt - || fail decode segmented $CAPNP convert packed:text $SCHEMA TestAllTypes < $TESTDATA/segmented-packed | cmp $TESTDATA/pretty.txt - || fail decode segmented-packed $CAPNP convert binary:packed < $TESTDATA/binary | cmp $TESTDATA/packed - || fail binary to packed $CAPNP convert packed:binary < $TESTDATA/packed | cmp $TESTDATA/binary - || fail packed to binary $CAPNP convert binary:json $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/pretty.json - || fail binary to json $CAPNP convert binary:json --short $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/short.json - || fail binary to short json $CAPNP convert json:binary $SCHEMA TestAllTypes < $TESTDATA/pretty.json | cmp $TESTDATA/binary - || fail json to binary $CAPNP convert json:binary $SCHEMA TestAllTypes < $TESTDATA/short.json | cmp $TESTDATA/binary - || fail short json to binary $CAPNP convert json:binary $JSON_SCHEMA TestJsonAnnotations -I"$SRCDIR" < $TESTDATA/annotated.json | cmp $TESTDATA/annotated-json.binary - || fail annotated json to binary $CAPNP convert binary:json $JSON_SCHEMA TestJsonAnnotations -I"$SRCDIR" < $TESTDATA/annotated-json.binary | cmp $TESTDATA/annotated.json - || fail annotated binary to json [ "$(echo '(foo = (text = "abc"))' | $CAPNP convert text:text "$SRCDIR/capnp/test.capnp" BrandedAlias)" = '(foo = (text = "abc"), uv = void)' ] || fail branded alias [ "$(echo '(foo = (text = "abc"))' | $CAPNP convert text:text "$SRCDIR/capnp/test.capnp" BrandedAlias.Inner)" = '(foo = (text = "abc"))' ] || fail branded alias [ "$(echo '(foo = (text = "abc"))' | $CAPNP convert text:text "$SRCDIR/capnp/test.capnp" 'TestGenerics(BoxedText, Text)')" = '(foo = (text = "abc"), uv = void)' ] || fail branded alias [ "$(echo '(baz = (text = "abc"))' | $CAPNP convert text:text "$SRCDIR/capnp/test.capnp" 'TestGenerics(TestAllTypes, List(Int32)).Inner2(BoxedText)')" = '(baz = (text = "abc"))' ] || fail branded alias # ======================================================================================== # DEPRECATED encode/decode $CAPNP encode $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/binary - || fail encode $CAPNP encode --flat $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/flat - || fail encode flat $CAPNP encode --packed $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/packed - || fail encode packed $CAPNP encode --packed --flat $SCHEMA TestAllTypes < $TESTDATA/short.txt | cmp $TESTDATA/packedflat - || fail encode packedflat $CAPNP encode $SCHEMA TestAllTypes < $TESTDATA/pretty.txt | cmp $TESTDATA/binary - || fail parse pretty $CAPNP decode $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/pretty.txt - || fail decode $CAPNP decode --flat $SCHEMA TestAllTypes < $TESTDATA/flat | cmp $TESTDATA/pretty.txt - || fail decode flat $CAPNP decode --packed $SCHEMA TestAllTypes < $TESTDATA/packed | cmp $TESTDATA/pretty.txt - || fail decode packed $CAPNP decode --packed --flat $SCHEMA TestAllTypes < $TESTDATA/packedflat | cmp $TESTDATA/pretty.txt - || fail decode packedflat $CAPNP decode --short $SCHEMA TestAllTypes < $TESTDATA/binary | cmp $TESTDATA/short.txt - || fail decode short $CAPNP decode $SCHEMA TestAllTypes < $TESTDATA/segmented | cmp $TESTDATA/pretty.txt - || fail decode segmented $CAPNP decode --packed $SCHEMA TestAllTypes < $TESTDATA/segmented-packed | cmp $TESTDATA/pretty.txt - || fail decode segmented-packed # ======================================================================================== # eval test_eval() { test "x`$CAPNP eval $SCHEMA $1 | tr -d '\r'`" = "x$2" || fail eval "$1 == $2" } test_eval TestDefaults.uInt32Field 3456789012 test_eval TestDefaults.structField.textField '"baz"' test_eval TestDefaults.int8List "[111, -111]" test_eval 'TestDefaults.structList[1].textField' '"structlist 2"' test_eval globalPrintableStruct '(someText = "foo")' test_eval TestConstants.enumConst corge test_eval 'TestListDefaults.lists.int32ListList[2][0]' 12341234 test "x`$CAPNP eval $SCHEMA -ojson globalPrintableStruct | tr -d '\r'`" = "x{\"someText\": \"foo\"}" || fail eval json "globalPrintableStruct == {someText = \"foo\"}" $CAPNP eval $TESTDATA/no-file-id.capnp.nobuild foo >/dev/null || fail eval "file without file ID can be parsed" test "x`$CAPNP eval $TESTDATA/no-file-id.capnp.nobuild foo | tr -d '\r'`" = 'x"bar"' || fail eval "file without file ID parsed correctly" $CAPNP compile --no-standard-import --src-prefix="$PREFIX" -ofoo $TESTDATA/errors.capnp.nobuild 2>&1 | sed -e "s,^.*errors[.]capnp[.]nobuild:,file:,g" | tr -d '\r' | diff -u $TESTDATA/errors.txt - || fail error output $CAPNP compile --no-standard-import --src-prefix="$PREFIX" -ofoo $TESTDATA/errors2.capnp.nobuild 2>&1 | sed -e "s,^.*errors2[.]capnp[.]nobuild:,file:,g" | tr -d '\r' | diff -u $TESTDATA/errors2.txt - || fail error2 output capnproto-c++-1.1.0/src/capnp/compiler/type-id.h0000644000175000017500000000364014527152321022175 0ustar00kentonkenton00000000000000// Copyright (c) 2017 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName); uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex); uint64_t generateMethodParamsId(uint64_t parentId, uint16_t methodOrdinal, bool isResults); // Generate a default type ID for various symbols. These are used only if the developer did not // specify an ID explicitly. // // The returned ID always has the most-significant bit set. The remaining bits are generated // pseudo-randomly from the input using an algorithm that should produce a uniform distribution of // IDs. } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compiler/capnp.c++0000644000175000017500000021744714731420004022051 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 // Request 64-bit off_t and ino_t, otherwise this code will break when either value exceeds 2^32. #endif #if _WIN32 #include #endif #include "lexer.h" #include "parser.h" #include "compiler.h" #include "module-loader.h" #include "node-translator.h" #include #include #include #include #include #include #include "../message.h" #include #include #include #include #include #include #include #include #include #include #include #include #if _WIN32 #include #include #include #undef CONST #else #include #endif #if HAVE_CONFIG_H #include "config.h" #endif #ifndef VERSION #define VERSION "(unknown)" #endif namespace capnp { namespace compiler { static const char VERSION_STRING[] = "Cap'n Proto version " VERSION; class CompilerMain final: public GlobalErrorReporter { public: explicit CompilerMain(kj::ProcessContext& context) : context(context), disk(kj::newDiskFilesystem()), loader(*this) {} kj::MainFunc getMain() { if (context.getProgramName().endsWith("capnpc") || context.getProgramName().endsWith("capnpc.exe")) { kj::MainBuilder builder(context, VERSION_STRING, "Compiles Cap'n Proto schema files and generates corresponding source code in one or " "more languages."); addGlobalOptions(builder); addCompileOptions(builder); builder.addOption({'i', "generate-id"}, KJ_BIND_METHOD(*this, generateId), "Generate a new 64-bit unique ID for use in a Cap'n Proto schema."); return builder.build(); } else { kj::MainBuilder builder(context, VERSION_STRING, "Command-line tool for Cap'n Proto development and debugging."); builder.addSubCommand("compile", KJ_BIND_METHOD(*this, getCompileMain), "Generate source code from schema files.") .addSubCommand("id", KJ_BIND_METHOD(*this, getGenIdMain), "Generate a new unique ID.") .addSubCommand("convert", KJ_BIND_METHOD(*this, getConvertMain), "Convert messages between binary, text, JSON, etc.") .addSubCommand("decode", KJ_BIND_METHOD(*this, getDecodeMain), "DEPRECATED (use `convert`)") .addSubCommand("encode", KJ_BIND_METHOD(*this, getEncodeMain), "DEPRECATED (use `convert`)") .addSubCommand("eval", KJ_BIND_METHOD(*this, getEvalMain), "Evaluate a const from a schema file."); addGlobalOptions(builder); return builder.build(); } } kj::MainFunc getCompileMain() { kj::MainBuilder builder(context, VERSION_STRING, "Compiles Cap'n Proto schema files and generates corresponding source code in one or " "more languages."); addGlobalOptions(builder); addCompileOptions(builder); return builder.build(); } kj::MainFunc getGenIdMain() { return kj::MainBuilder(context, VERSION_STRING, "Generates a new 64-bit unique ID for use in a Cap'n Proto schema.") .callAfterParsing(KJ_BIND_METHOD(*this, generateId)) .build(); } kj::MainFunc getConvertMain() { // Only parse the schemas we actually need for decoding. compileEagerness = Compiler::NODE; // Drop annotations since we don't need them. This avoids importing files like c++.capnp. annotationFlag = Compiler::DROP_ANNOTATIONS; kj::MainBuilder builder(context, VERSION_STRING, "Converts messages between formats. Reads a stream of messages from stdin in format " " and writes them to stdout in format . Valid formats are:\n" " binary standard binary format\n" " packed packed binary format (deflates zeroes)\n" " flat binary single segment, no segment table (rare)\n" " flat-packed flat and packed\n" " canonical canonicalized binary single segment, no segment table\n" " text schema language struct literal format\n" " json JSON format\n" "When using \"text\" or \"json\" format, you must specify and " "(but they are ignored and can be omitted for binary-to-binary conversions). " " names names a struct type defined in , which is the root type " "of the message(s)."); addGlobalOptions(builder); builder.addOption({"short"}, KJ_BIND_METHOD(*this, printShort), "Write text or JSON output in short (non-pretty) format. Each message will " "be printed on one line, without using whitespace to improve readability.") .addOptionWithArg({"segment-size"}, KJ_BIND_METHOD(*this, setSegmentSize), "", "For binary output, sets the preferred segment size on the MallocMessageBuilder to " "words and turns off heuristic growth. This flag is mainly useful " "for testing. Without it, each message will be written as a single " "segment.") .addOption({"quiet"}, KJ_BIND_METHOD(*this, setQuiet), "Do not print warning messages about the input being in the wrong format. " "Use this if you find the warnings are wrong (but also let us know so " "we can improve them).") .expectArg(":", KJ_BIND_METHOD(*this, setConversion)) .expectOptionalArg("", KJ_BIND_METHOD(*this, addSource)) .expectOptionalArg("", KJ_BIND_METHOD(*this, setRootType)) .callAfterParsing(KJ_BIND_METHOD(*this, convert)); return builder.build(); } kj::MainFunc getDecodeMain() { // Only parse the schemas we actually need for decoding. compileEagerness = Compiler::NODE; // Drop annotations since we don't need them. This avoids importing files like c++.capnp. annotationFlag = Compiler::DROP_ANNOTATIONS; kj::MainBuilder builder(context, VERSION_STRING, "Decodes one or more encoded Cap'n Proto messages as text. The messages have root " "type defined in . Messages are read from standard input and " "by default are expected to be in standard Cap'n Proto serialization format."); addGlobalOptions(builder); builder.addOption({"flat"}, KJ_BIND_METHOD(*this, codeFlat), "Interpret the input as one large single-segment message rather than a " "stream in standard serialization format. (Rarely used.)") .addOption({'p', "packed"}, KJ_BIND_METHOD(*this, codePacked), "Expect the input to be packed using standard Cap'n Proto packing, which " "deflates zero-valued bytes. (This reads messages written with " "capnp::writePackedMessage*() from . Do not use " "this for messages written with capnp::writeMessage*() from " ".)") .addOption({"short"}, KJ_BIND_METHOD(*this, printShort), "Print in short (non-pretty) format. Each message will be printed on one " "line, without using whitespace to improve readability.") .addOption({"quiet"}, KJ_BIND_METHOD(*this, setQuiet), "Do not print warning messages about the input being in the wrong format. " "Use this if you find the warnings are wrong (but also let us know so " "we can improve them).") .expectArg("", KJ_BIND_METHOD(*this, addSource)) .expectArg("", KJ_BIND_METHOD(*this, setRootType)) .callAfterParsing(KJ_BIND_METHOD(*this, decode)); return builder.build(); } kj::MainFunc getEncodeMain() { // Only parse the schemas we actually need for decoding. compileEagerness = Compiler::NODE; // Drop annotations since we don't need them. This avoids importing files like c++.capnp. annotationFlag = Compiler::DROP_ANNOTATIONS; kj::MainBuilder builder(context, VERSION_STRING, "Encodes one or more textual Cap'n Proto messages to binary. The messages have root " "type defined in . Messages are read from standard input. Each " "message is a parenthesized struct literal, like the format used to specify constants " "and default values of struct type in the schema language. For example:\n" " (foo = 123, bar = \"hello\", baz = [true, false, true])\n" "The input may contain any number of such values; each will be encoded as a separate " "message.", "Note that the current implementation reads the entire input into memory before " "beginning to encode. A better implementation would read and encode one message at " "a time."); addGlobalOptions(builder); builder.addOption({"flat"}, KJ_BIND_METHOD(*this, codeFlat), "Expect only one input value, serializing it as a single-segment message " "with no framing.") .addOption({'p', "packed"}, KJ_BIND_METHOD(*this, codePacked), "Pack the output message with standard Cap'n Proto packing, which " "deflates zero-valued bytes. (This writes messages using " "capnp::writePackedMessage() from . Without " "this, capnp::writeMessage() from is used.)") .addOptionWithArg({"segment-size"}, KJ_BIND_METHOD(*this, setSegmentSize), "", "Sets the preferred segment size on the MallocMessageBuilder to " "words and turns off heuristic growth. This flag is mainly useful " "for testing. Without it, each message will be written as a single " "segment.") .expectArg("", KJ_BIND_METHOD(*this, addSource)) .expectArg("", KJ_BIND_METHOD(*this, setRootType)) .callAfterParsing(KJ_BIND_METHOD(*this, encode)); return builder.build(); } kj::MainFunc getEvalMain() { // Only parse the schemas we actually need for decoding. compileEagerness = Compiler::NODE; // Drop annotations since we don't need them. This avoids importing files like c++.capnp. annotationFlag = Compiler::DROP_ANNOTATIONS; // Default convert to text unless -o is given. convertTo = Format::TEXT; // When using `capnp eval`, type IDs don't really matter, because `eval` won't actually use // them for anything. When using Cap'n Proto an a config format -- the common use case for // `capnp eval` -- the exercise of adding a file ID to every file is pointless busy work. So, // we don't require it. loader.setFileIdsRequired(false); kj::MainBuilder builder(context, VERSION_STRING, "Prints (or encodes) the value of , which must be defined in . " " must refer to a const declaration, a field of a struct type (prints the default " "value), or a field or list element nested within some other value. Examples:\n" " capnp eval myschema.capnp MyType.someField\n" " capnp eval myschema.capnp someConstant\n" " capnp eval myschema.capnp someConstant.someField\n" " capnp eval myschema.capnp someConstant.someList[4]\n" " capnp eval myschema.capnp someConstant.someList[4].anotherField[1][2][3]\n" "Since consts can have complex struct types, and since you can define a const using " "import and variable substitution, this can be a convenient way to write text-format " "config files which are compiled to binary before deployment.", "By default the value is written in text format and can have any type. The -b, -p, " "and --flat flags specify binary output, in which case the const must be of struct " "type."); addGlobalOptions(builder); builder.addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setEvalOutputFormat), "", "Encode the output in the given format. See `capnp help convert` " "for a list of formats. Defaults to \"text\".") .addOption({'b', "binary"}, KJ_BIND_METHOD(*this, codeBinary), "same as -obinary") .addOption({"flat"}, KJ_BIND_METHOD(*this, codeFlat), "same as -oflat") .addOption({'p', "packed"}, KJ_BIND_METHOD(*this, codePacked), "same as -opacked") .addOption({"short"}, KJ_BIND_METHOD(*this, printShort), "If output format is text or JSON, write in short (non-pretty) format. The " "message will be printed on one line, without using whitespace to improve " "readability.") .expectArg("", KJ_BIND_METHOD(*this, addSource)) .expectArg("", KJ_BIND_METHOD(*this, evalConst)); return builder.build(); } void addGlobalOptions(kj::MainBuilder& builder) { builder.addOptionWithArg({'I', "import-path"}, KJ_BIND_METHOD(*this, addImportPath), "", "Add to the list of directories searched for non-relative " "imports (ones that start with a '/').") .addOption({"no-standard-import"}, KJ_BIND_METHOD(*this, noStandardImport), "Do not add any default import paths; use only those specified by -I. " "Otherwise, typically /usr/include and /usr/local/include are added by " "default."); } void addCompileOptions(kj::MainBuilder& builder) { builder.addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, addOutput), "[:]", "Generate source code for language in directory " "(default: current directory). actually specifies a plugin " "to use. If is a simple word, the compiler searches for a plugin " "called 'capnpc-' in $PATH. If is a file path " "containing slashes, it is interpreted as the exact plugin " "executable file name, and $PATH is not searched. If is '-', " "the compiler dumps the request to standard output.") .addOptionWithArg({"src-prefix"}, KJ_BIND_METHOD(*this, addSourcePrefix), "", "If a file specified for compilation starts with , remove " "the prefix for the purpose of deciding the names of output files. " "For example, the following command:\n" " capnp compile --src-prefix=foo/bar -oc++:corge foo/bar/baz/qux.capnp\n" "would generate the files corge/baz/qux.capnp.{h,c++}.") .expectOneOrMoreArgs("", KJ_BIND_METHOD(*this, addSource)) .callAfterParsing(KJ_BIND_METHOD(*this, generateOutput)); } // ===================================================================================== // shared options kj::MainBuilder::Validity addImportPath(kj::StringPtr path) { KJ_IF_MAYBE(dir, getSourceDirectory(path, false)) { loader.addImportPath(*dir); return true; } else { return "no such directory"; } } kj::MainBuilder::Validity noStandardImport() { addStandardImportPaths = false; return true; } kj::MainBuilder::Validity addSource(kj::StringPtr file) { if (!compilerConstructed) { compiler = compilerSpace.construct(annotationFlag); compilerConstructed = true; } if (addStandardImportPaths) { static constexpr kj::StringPtr STANDARD_IMPORT_PATHS[] = { "/usr/local/include"_kj, "/usr/include"_kj, #ifdef CAPNP_INCLUDE_DIR KJ_CONCAT(CAPNP_INCLUDE_DIR, _kj), #endif }; for (auto path: STANDARD_IMPORT_PATHS) { KJ_IF_MAYBE(dir, getSourceDirectory(path, false)) { loader.addImportPath(*dir); } else { // ignore standard path that doesn't exist } } addStandardImportPaths = false; } auto dirPathPair = interpretSourceFile(file); KJ_IF_MAYBE(module, loader.loadModule(dirPathPair.dir, dirPathPair.path)) { auto compiled = compiler->add(*module); compiler->eagerlyCompile(compiled.getId(), compileEagerness); sourceFiles.add(SourceFile { compiled.getId(), compiled, module->getSourceName(), &*module }); } else { return "no such file"; } return true; } public: // ===================================================================================== // "id" command kj::MainBuilder::Validity generateId() { context.exitInfo(kj::str("@0x", kj::hex(generateRandomId()))); KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT; } // ===================================================================================== // "compile" command kj::MainBuilder::Validity addOutput(kj::StringPtr spec) { KJ_IF_MAYBE(split, spec.findFirst(':')) { kj::StringPtr dir = spec.slice(*split + 1); auto plugin = spec.slice(0, *split); if (*split == 1 && (dir.startsWith("/") || dir.startsWith("\\"))) { // The colon is the second character and is immediately followed by a slash or backslash. // So, the user passed something like `-o c:/foo`. Is this a request to run the C plugin // and output to `/foo`? Or are we on Windows, and is this a request to run the plugin // `c:/foo`? KJ_IF_MAYBE(split2, dir.findFirst(':')) { // There are two colons. The first ':' was the second char, and was followed by '/' or // '\', e.g.: // capnp compile -o c:/foo.exe:bar // // In this case we can conclude that the second colon is actually meant to be the // plugin/location separator, and the first colon was simply signifying a drive letter. // // Proof by contradiction: // - Say that none of the colons were meant to be plugin/location separators; i.e. the // whole argument is meant to be a plugin indicator and the location defaults to ".". // -> In this case, the plugin path has two colons, which is not valid. // -> CONTRADICTION // - Say that the first colon was meant to be the plugin/location separator. // -> In this case, the second colon must be the drive letter separator for the // output location. // -> However, the output location begins with '/' or '\', which is not a drive letter. // -> CONTRADICTION // - Say that there are more colons beyond the first two, and one of these is meant to // be the plugin/location separator. // -> In this case, the plugin path has two or more colons, which is not valid. // -> CONTRADICTION // // We therefore conclude that the *second* colon is in fact the plugin/location separator. dir = dir.slice(*split2 + 1); plugin = spec.slice(0, *split2 + 2); #if _WIN32 } else { // The user wrote something like: // // capnp compile -o c:/foo/bar // // What does this mean? It depends on what system we're on. On a Unix system, the above // clearly is a request to run the `capnpc-c` plugin (perhaps to output C code) and write // to the directory /foo/bar. But on Windows, absolute paths do not start with '/', and // the above is actually a request to run the plugin `c:/foo/bar`, outputting to the // current directory. outputs.add(OutputDirective { spec.asArray(), nullptr }); return true; #endif } } struct stat stats; if (stat(dir.cStr(), &stats) < 0 || !S_ISDIR(stats.st_mode)) { return "output location is inaccessible or is not a directory"; } outputs.add(OutputDirective { plugin, disk->getCurrentPath().evalNative(dir) }); } else { outputs.add(OutputDirective { spec.asArray(), nullptr }); } return true; } kj::MainBuilder::Validity addSourcePrefix(kj::StringPtr prefix) { if (getSourceDirectory(prefix, true) == nullptr) { return "no such directory"; } else { return true; } } kj::MainBuilder::Validity generateOutput() { if (hadErrors()) { // Skip output if we had any errors. return true; } // We require one or more sources and if they failed to compile we quit above, so this should // pass. (This assertion also guarantees that `compiler` has been initialized.) KJ_ASSERT(sourceFiles.size() > 0, "Shouldn't have gotten here without sources."); if (outputs.size() == 0) { return "no outputs specified"; } MallocMessageBuilder message; auto request = message.initRoot(); auto version = request.getCapnpVersion(); version.setMajor(CAPNP_VERSION_MAJOR); version.setMinor(CAPNP_VERSION_MINOR); version.setMicro(CAPNP_VERSION_MICRO); auto schemas = compiler->getLoader().getAllLoaded(); auto nodes = request.initNodes(schemas.size()); for (size_t i = 0; i < schemas.size(); i++) { nodes.setWithCaveats(i, schemas[i].getProto()); } request.adoptSourceInfo(compiler->getAllSourceInfo(message.getOrphanage())); auto requestedFiles = request.initRequestedFiles(sourceFiles.size()); for (size_t i = 0; i < sourceFiles.size(); i++) { auto requestedFile = requestedFiles[i]; requestedFile.setId(sourceFiles[i].id); requestedFile.setFilename(sourceFiles[i].name); requestedFile.adoptImports(compiler->getFileImportTable( *sourceFiles[i].module, Orphanage::getForMessageContaining(requestedFile))); // Populate FileSourceInfo with identifier resolutions, including type IDs and member details. auto fileSourceInfo = requestedFile.initFileSourceInfo(); const auto resolutions = sourceFiles[i].module->getResolutions(); auto identifiers = fileSourceInfo.initIdentifiers(resolutions.size()); for (size_t j = 0; j < resolutions.size(); j++) { auto identifier = identifiers[j]; identifier.setStartByte(resolutions[j].startByte); identifier.setEndByte(resolutions[j].endByte); KJ_SWITCH_ONEOF(resolutions[j].target) { KJ_CASE_ONEOF(type, Resolution::Type) { identifier.setTypeId(type.typeId); } KJ_CASE_ONEOF(member, Resolution::Member) { identifier.initMember(); auto identifier_member = identifier.getMember(); identifier_member.setParentTypeId(member.parentTypeId); identifier_member.setOrdinal(member.ordinal); } } } } for (auto& output: outputs) { if (kj::str(output.name) == "-") { writeMessageToFd(STDOUT_FILENO, message); continue; } int pipeFds[2]; KJ_SYSCALL(kj::miniposix::pipe(pipeFds)); kj::String exeName; bool shouldSearchPath = true; for (char c: output.name) { #if _WIN32 if (c == '/' || c == '\\') { #else if (c == '/') { #endif shouldSearchPath = false; break; } } if (shouldSearchPath) { exeName = kj::str("capnpc-", output.name); } else { exeName = kj::heapString(output.name); } kj::Array pwd = kj::heapArray(256); while (getcwd(pwd.begin(), pwd.size()) == nullptr) { KJ_REQUIRE(pwd.size() < 8192, "WTF your working directory path is more than 8k?"); pwd = kj::heapArray(pwd.size() * 2); } #if _WIN32 int oldStdin; KJ_SYSCALL(oldStdin = dup(STDIN_FILENO)); intptr_t child; #else // _WIN32 pid_t child; KJ_SYSCALL(child = fork()); if (child == 0) { // I am the child! KJ_SYSCALL(close(pipeFds[1])); #endif // _WIN32, else KJ_SYSCALL(dup2(pipeFds[0], STDIN_FILENO)); KJ_SYSCALL(close(pipeFds[0])); KJ_IF_MAYBE(d, output.dir) { #if _WIN32 KJ_SYSCALL(SetCurrentDirectoryW(d->forWin32Api(true).begin()), d->toWin32String(true)); #else auto wd = d->toString(true); KJ_SYSCALL(chdir(wd.cStr()), wd); KJ_SYSCALL(setenv("PWD", wd.cStr(), true)); #endif } #if _WIN32 // MSVCRT's spawn*() don't correctly escape arguments, which is necessary on Windows // since the underlying system call takes a single command line string rather than // an arg list. We do the escaping ourselves by wrapping the name in quotes. We know // that exeName itself can't contain quotes (since filenames aren't allowed to contain // quotes on Windows), so we don't have to account for those. KJ_ASSERT(exeName.findFirst('\"') == nullptr, "Windows filenames can't contain quotes", exeName); auto escapedExeName = kj::str("\"", exeName, "\""); #endif if (shouldSearchPath) { #if _WIN32 child = _spawnlp(_P_NOWAIT, exeName.cStr(), escapedExeName.cStr(), nullptr); #else execlp(exeName.cStr(), exeName.cStr(), nullptr); #endif } else { #if _WIN32 if (!exeName.startsWith("/") && !exeName.startsWith("\\") && !(exeName.size() >= 2 && exeName[1] == ':')) { #else if (!exeName.startsWith("/")) { #endif // The name is relative. Prefix it with our original working directory path. exeName = kj::str(pwd.begin(), "/", exeName); } #if _WIN32 child = _spawnl(_P_NOWAIT, exeName.cStr(), escapedExeName.cStr(), nullptr); #else execl(exeName.cStr(), exeName.cStr(), nullptr); #endif } #if _WIN32 if (child == -1) { #endif int error = errno; if (error == ENOENT) { context.exitError(kj::str(output.name, ": no such plugin (executable should be '", exeName, "')")); } else { #if _WIN32 KJ_FAIL_SYSCALL("spawn()", error); #else KJ_FAIL_SYSCALL("exec()", error); #endif } #if _WIN32 } // Restore stdin. KJ_SYSCALL(dup2(oldStdin, STDIN_FILENO)); KJ_SYSCALL(close(oldStdin)); // Restore current directory. KJ_SYSCALL(chdir(pwd.begin()), pwd.begin()); #else // _WIN32 } KJ_SYSCALL(close(pipeFds[0])); #endif // _WIN32, else writeMessageToFd(pipeFds[1], message); KJ_SYSCALL(close(pipeFds[1])); #if _WIN32 int status; if (_cwait(&status, child, 0) == -1) { KJ_FAIL_SYSCALL("_cwait()", errno); } if (status != 0) { context.error(kj::str(output.name, ": plugin failed: exit code ", status)); } #else // _WIN32 int status; KJ_SYSCALL(waitpid(child, &status, 0)); if (WIFSIGNALED(status)) { context.error(kj::str(output.name, ": plugin failed: ", strsignal(WTERMSIG(status)))); } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { context.error(kj::str(output.name, ": plugin failed: exit code ", WEXITSTATUS(status))); } #endif // _WIN32, else } return true; } // ===================================================================================== // "convert" command private: enum class Format { BINARY, PACKED, FLAT, FLAT_PACKED, CANONICAL, TEXT, JSON }; kj::Maybe parseFormatName(kj::StringPtr name) { if (name == "binary" ) return Format::BINARY; if (name == "packed" ) return Format::PACKED; if (name == "flat" ) return Format::FLAT; if (name == "flat-packed") return Format::FLAT_PACKED; if (name == "canonical" ) return Format::CANONICAL; if (name == "text" ) return Format::TEXT; if (name == "json" ) return Format::JSON; return nullptr; } kj::StringPtr toString(Format format) { switch (format) { case Format::BINARY : return "binary"; case Format::PACKED : return "packed"; case Format::FLAT : return "flat"; case Format::FLAT_PACKED: return "flat-packed"; case Format::CANONICAL : return "canonical"; case Format::TEXT : return "text"; case Format::JSON : return "json"; } KJ_UNREACHABLE; } Format formatFromDeprecatedFlags(Format defaultFormat) { // For deprecated commands "decode" and "encode". if (flat) { if (packed) { return Format::FLAT_PACKED; } else { return Format::FLAT; } } if (packed) { return Format::PACKED; } else if (binary) { return Format::BINARY; } else { return defaultFormat; } } kj::MainBuilder::Validity verifyRequirements(Format format) { if ((format == Format::TEXT || format == Format::JSON) && rootType == StructSchema()) { return kj::str("format requires schema: ", toString(format)); } else { return true; } } public: kj::MainBuilder::Validity setConversion(kj::StringPtr conversion) { KJ_IF_MAYBE(colon, conversion.findFirst(':')) { auto from = kj::str(conversion.slice(0, *colon)); auto to = conversion.slice(*colon + 1); KJ_IF_MAYBE(f, parseFormatName(from)) { convertFrom = *f; } else { return kj::str("unknown format: ", from); } KJ_IF_MAYBE(t, parseFormatName(to)) { convertTo = *t; } else { return kj::str("unknown format: ", to); } if (convertFrom == Format::JSON || convertTo == Format::JSON) { // We need annotations to process JSON. // TODO(someday): Find a way that we can process annotations from json.capnp without // requiring other annotation-only imports like c++.capnp annotationFlag = Compiler::COMPILE_ANNOTATIONS; } return true; } else { return "invalid conversion, format is: :"; } } kj::MainBuilder::Validity convert() { { auto result = verifyRequirements(convertFrom); if (result.getError() != nullptr) return result; } { auto result = verifyRequirements(convertTo); if (result.getError() != nullptr) return result; } kj::FdInputStream rawInput(STDIN_FILENO); kj::BufferedInputStreamWrapper input(rawInput); kj::FdOutputStream output(STDOUT_FILENO); if (!quiet) { auto result = checkPlausibility(convertFrom, input.getReadBuffer()); if (result.getError() != nullptr) { return kj::mv(result); } } while (input.tryGetReadBuffer().size() > 0) { readOneAndConvert(input, output); } context.exit(); KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT; } private: kj::Vector readAll(kj::BufferedInputStreamWrapper& input) { kj::Vector allBytes; for (;;) { auto buffer = input.tryGetReadBuffer(); if (buffer.size() == 0) break; allBytes.addAll(buffer); input.skip(buffer.size()); } return allBytes; } kj::String readOneText(kj::BufferedInputStreamWrapper& input) { // Consume and return one parentheses-delimited message from the input. // // Accounts for nested parentheses, comments, and string literals. enum { NORMAL, COMMENT, QUOTE, QUOTE_ESCAPE, DQUOTE, DQUOTE_ESCAPE } state = NORMAL; uint depth = 0; bool sawClose = false; kj::Vector chars; for (;;) { auto buffer = input.tryGetReadBuffer(); if (buffer == nullptr) { // EOF chars.add('\0'); return kj::String(chars.releaseAsArray()); } for (auto i: kj::indices(buffer)) { char c = buffer[i]; switch (state) { case NORMAL: switch (c) { case '#': state = COMMENT; break; case '(': if (depth == 0 && sawClose) { // We already got one complete message. This is the start of the next message. // Stop here. chars.addAll(buffer.slice(0, i)); chars.add('\0'); input.skip(i); return kj::String(chars.releaseAsArray()); } ++depth; break; case ')': if (depth > 0) { if (--depth == 0) { sawClose = true; } } break; default: break; } break; case COMMENT: switch (c) { case '\n': state = NORMAL; break; default: break; } break; case QUOTE: switch (c) { case '\'': state = NORMAL; break; case '\\': state = QUOTE_ESCAPE; break; default: break; } break; case QUOTE_ESCAPE: break; case DQUOTE: switch (c) { case '\"': state = NORMAL; break; case '\\': state = DQUOTE_ESCAPE; break; default: break; } break; case DQUOTE_ESCAPE: break; } } chars.addAll(buffer); input.skip(buffer.size()); } } kj::String readOneJson(kj::BufferedInputStreamWrapper& input) { // Consume and return one brace-delimited message from the input. // // Accounts for nested braces, string literals, and comments starting with # or //. Technically // JSON does not permit comments but this code is lenient in case we change things later. enum { NORMAL, SLASH, COMMENT, QUOTE, QUOTE_ESCAPE, DQUOTE, DQUOTE_ESCAPE } state = NORMAL; uint depth = 0; bool sawClose = false; kj::Vector chars; for (;;) { auto buffer = input.tryGetReadBuffer(); if (buffer == nullptr) { // EOF chars.add('\0'); return kj::String(chars.releaseAsArray()); } for (auto i: kj::indices(buffer)) { char c = buffer[i]; switch (state) { case SLASH: if (c == '/') { state = COMMENT; break; } KJ_FALLTHROUGH; case NORMAL: switch (c) { case '#': state = COMMENT; break; case '/': state = SLASH; break; case '{': if (depth == 0 && sawClose) { // We already got one complete message. This is the start of the next message. // Stop here. chars.addAll(buffer.slice(0, i)); chars.add('\0'); input.skip(i); return kj::String(chars.releaseAsArray()); } ++depth; break; case '}': if (depth > 0) { if (--depth == 0) { sawClose = true; } } break; default: break; } break; case COMMENT: switch (c) { case '\n': state = NORMAL; break; default: break; } break; case QUOTE: switch (c) { case '\'': state = NORMAL; break; case '\\': state = QUOTE_ESCAPE; break; default: break; } break; case QUOTE_ESCAPE: break; case DQUOTE: switch (c) { case '\"': state = NORMAL; break; case '\\': state = DQUOTE_ESCAPE; break; default: break; } break; case DQUOTE_ESCAPE: break; } } chars.addAll(buffer); input.skip(buffer.size()); } } class ParseErrorCatcher: public kj::ExceptionCallback { public: ParseErrorCatcher(kj::ProcessContext& context): context(context) {} ~ParseErrorCatcher() noexcept(false) { if (!unwindDetector.isUnwinding()) { KJ_IF_MAYBE(e, exception) { context.error(kj::str( "*** ERROR CONVERTING PREVIOUS MESSAGE ***\n" "The following error occurred while converting the message above.\n" "This probably means the input data is invalid/corrupted.\n", "Exception description: ", e->getDescription(), "\n" "Code location: ", e->getFile(), ":", e->getLine(), "\n" "*** END ERROR ***")); } } } void onRecoverableException(kj::Exception&& e) { // Only capture the first exception, on the assumption that later exceptions are probably // just cascading problems. if (exception == nullptr) { exception = kj::mv(e); } } private: kj::ProcessContext& context; kj::Maybe exception; kj::UnwindDetector unwindDetector; }; void readOneAndConvert(kj::BufferedInputStreamWrapper& input, kj::OutputStream& output) { // Since this is a debug tool, lift the usual security limits. Worse case is the process // crashes or has to be killed. ReaderOptions options; options.nestingLimit = kj::maxValue; options.traversalLimitInWords = kj::maxValue; ParseErrorCatcher parseErrorCatcher(context); switch (convertFrom) { case Format::BINARY: { capnp::InputStreamMessageReader message(input, options); return writeConversion(message.getRoot(), output); } case Format::PACKED: { capnp::PackedMessageReader message(input, options); return writeConversion(message.getRoot(), output); } case Format::FLAT: case Format::CANONICAL: { auto allBytes = readAll(input); // Technically we don't know if the bytes are aligned so we'd better copy them to a new // array. Note that if we have a non-whole number of words we chop off the straggler // bytes. This is fine because if those bytes are actually part of the message we will // hit an error later and if they are not then who cares? auto words = kj::heapArray(allBytes.size() / sizeof(word)); memcpy(words.begin(), allBytes.begin(), words.size() * sizeof(word)); kj::ArrayPtr segments[1] = { words }; SegmentArrayMessageReader message(segments, options); if (convertFrom == Format::CANONICAL) { KJ_REQUIRE(message.isCanonical()); } return writeConversion(message.getRoot(), output); } case Format::FLAT_PACKED: { auto allBytes = readAll(input); auto words = kj::heapArray(computeUnpackedSizeInWords(allBytes)); kj::ArrayInputStream input(allBytes); capnp::_::PackedInputStream unpacker(input); unpacker.read(words.asBytes().begin(), words.asBytes().size()); word dummy; KJ_ASSERT(unpacker.tryRead(&dummy, sizeof(dummy), sizeof(dummy)) == 0); kj::ArrayPtr segments[1] = { words }; SegmentArrayMessageReader message(segments, options); return writeConversion(message.getRoot(), output); } case Format::TEXT: { auto text = readOneText(input); MallocMessageBuilder message; TextCodec codec; codec.setPrettyPrint(pretty); auto root = message.initRoot(rootType); codec.decode(text, root); return writeConversion(root.asReader(), output); } case Format::JSON: { auto text = readOneJson(input); MallocMessageBuilder message; JsonCodec codec; codec.setPrettyPrint(pretty); codec.handleByAnnotation(rootType); auto root = message.initRoot(rootType); codec.decode(text, root); return writeConversion(root.asReader(), output); } } KJ_UNREACHABLE; } void writeConversion(AnyStruct::Reader reader, kj::OutputStream& output) { switch (convertTo) { case Format::BINARY: { MallocMessageBuilder message( segmentSize == 0 ? SUGGESTED_FIRST_SEGMENT_WORDS : segmentSize, segmentSize == 0 ? SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy::FIXED_SIZE); message.setRoot(reader); capnp::writeMessage(output, message); return; } case Format::PACKED: { MallocMessageBuilder message( segmentSize == 0 ? SUGGESTED_FIRST_SEGMENT_WORDS : segmentSize, segmentSize == 0 ? SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy::FIXED_SIZE); message.setRoot(reader); capnp::writePackedMessage(output, message); return; } case Format::FLAT: { auto words = kj::heapArray(reader.totalSize().wordCount + 1); memset(words.begin(), 0, words.asBytes().size()); copyToUnchecked(reader, words); output.write(words.begin(), words.asBytes().size()); return; } case Format::FLAT_PACKED: { auto words = kj::heapArray(reader.totalSize().wordCount + 1); memset(words.begin(), 0, words.asBytes().size()); copyToUnchecked(reader, words); kj::BufferedOutputStreamWrapper buffered(output); capnp::_::PackedOutputStream packed(buffered); packed.write(words.begin(), words.asBytes().size()); return; } case Format::CANONICAL: { auto words = reader.canonicalize(); output.write(words.begin(), words.asBytes().size()); return; } case Format::TEXT: { TextCodec codec; codec.setPrettyPrint(pretty); auto text = codec.encode(reader.as(rootType)); output.write({text.asBytes(), kj::StringPtr("\n").asBytes()}); return; } case Format::JSON: { JsonCodec codec; codec.setPrettyPrint(pretty); codec.handleByAnnotation(rootType); auto text = codec.encode(reader.as(rootType)); output.write({text.asBytes(), kj::StringPtr("\n").asBytes()}); return; } } KJ_UNREACHABLE; } public: // ===================================================================================== // "decode" command kj::MainBuilder::Validity codeBinary() { if (packed) return "cannot be used with --packed"; if (flat) return "cannot be used with --flat"; binary = true; return true; } kj::MainBuilder::Validity codeFlat() { if (binary) return "cannot be used with --binary"; flat = true; return true; } kj::MainBuilder::Validity codePacked() { if (binary) return "cannot be used with --binary"; packed = true; return true; } kj::MainBuilder::Validity printShort() { pretty = false; return true; } kj::MainBuilder::Validity setQuiet() { quiet = true; return true; } kj::MainBuilder::Validity setSegmentSize(kj::StringPtr size) { if (flat) return "cannot be used with --flat"; char* end; segmentSize = strtol(size.cStr(), &end, 0); if (size.size() == 0 || *end != '\0') { return "not an integer"; } return true; } kj::MainBuilder::Validity setRootType(kj::StringPtr input) { KJ_ASSERT(sourceFiles.size() == 1); class CliArgumentErrorReporter: public ErrorReporter { public: void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { if (startByte < endByte) { error = kj::str(startByte + 1, "-", endByte, ": ", message); } else if (startByte > 0) { error = kj::str(startByte + 1, ": ", message); } else { error = kj::str(message); } } bool hadErrors() override { return error != nullptr; } kj::MainBuilder::Validity getValidity() { KJ_IF_MAYBE(e, error) { return kj::mv(*e); } else { return true; } } private: kj::Maybe error; }; CliArgumentErrorReporter errorReporter; capnp::MallocMessageBuilder tokenArena; auto lexedTokens = tokenArena.initRoot(); lex(input, lexedTokens, errorReporter); CapnpParser parser(tokenArena.getOrphanage(), errorReporter); auto tokens = lexedTokens.asReader().getTokens(); CapnpParser::ParserInput parserInput(tokens.begin(), tokens.end()); bool success = false; if (parserInput.getPosition() == tokens.end()) { // Empty argument? errorReporter.addError(0, 0, "Couldn't parse type name."); } else { KJ_IF_MAYBE(expression, parser.getParsers().expression(parserInput)) { // The input is expected to contain a *single* expression. if (parserInput.getPosition() == tokens.end()) { // Hooray, now parse it. KJ_IF_MAYBE(compiledType, sourceFiles[0].compiled.evalType(expression->getReader(), errorReporter)) { KJ_IF_MAYBE(type, compiledType->getSchema()) { if (type->isStruct()) { rootType = type->asStruct(); success = true; } else { errorReporter.addError(0, 0, "Type is not a struct."); } } else { // Apparently named a file scope. errorReporter.addError(0, 0, "Type is not a struct."); } } } else { errorReporter.addErrorOn(parserInput.current(), "Couldn't parse type name."); } } else { auto best = parserInput.getBest(); if (best == tokens.end()) { errorReporter.addError(input.size(), input.size(), "Couldn't parse type name."); } else { errorReporter.addErrorOn(*best, "Couldn't parse type name."); } } } KJ_ASSERT(success || errorReporter.hadErrors()); return errorReporter.getValidity(); } kj::MainBuilder::Validity decode() { convertTo = Format::TEXT; convertFrom = formatFromDeprecatedFlags(Format::BINARY); return convert(); } private: enum Plausibility { IMPOSSIBLE, IMPLAUSIBLE, WRONG_TYPE, PLAUSIBLE }; bool plausibleOrWrongType(Plausibility p) { return p == PLAUSIBLE || p == WRONG_TYPE; } Plausibility isPlausiblyFlat(kj::ArrayPtr prefix, uint segmentCount = 1) { if (prefix.size() < 8) { // Not enough prefix to say. return PLAUSIBLE; } if ((prefix[0] & 3) == 2) { // Far pointer. Verify the segment ID. uint32_t segmentId = prefix[4] | (prefix[5] << 8) | (prefix[6] << 16) | (prefix[7] << 24); if (segmentId == 0 || segmentId >= segmentCount) { return IMPOSSIBLE; } else { return PLAUSIBLE; } } if ((prefix[0] & 3) != 0) { // Not a struct pointer. return IMPOSSIBLE; } if ((prefix[3] & 0x80) != 0) { if (prefix[0] == 0xff && prefix[1] == 0xff && prefix[2] == 0xff && prefix[3] == 0xff && prefix[4] == 0 && prefix[5] == 0 && prefix[6] == 0 && prefix[7] == 0) { // This is an empty struct with offset of -1. That's valid. } else { // Offset is negative (invalid). return IMPOSSIBLE; } } if ((prefix[3] & 0xe0) != 0) { // Offset is over a gigabyte (implausible). return IMPLAUSIBLE; } uint data = prefix[4] | (prefix[5] << 8); uint pointers = prefix[6] | (prefix[7] << 8); if (data + pointers > 2048) { // Root struct is huge (over 16 KiB). return IMPLAUSIBLE; } auto structSchema = rootType.getProto().getStruct(); if ((data < structSchema.getDataWordCount() && pointers > structSchema.getPointerCount()) || (data > structSchema.getDataWordCount() && pointers < structSchema.getPointerCount())) { // Struct is neither older nor newer than the schema. return WRONG_TYPE; } if (data > structSchema.getDataWordCount() && data - structSchema.getDataWordCount() > 128) { // Data section appears to have grown by 1k (128 words). This seems implausible. return WRONG_TYPE; } if (pointers > structSchema.getPointerCount() && pointers - structSchema.getPointerCount() > 128) { // Pointer section appears to have grown by 1k (128 words). This seems implausible. return WRONG_TYPE; } return PLAUSIBLE; } Plausibility isPlausiblyBinary(kj::ArrayPtr prefix) { if (prefix.size() < 8) { // Not enough prefix to say. return PLAUSIBLE; } uint32_t segmentCount = prefix[0] | (prefix[1] << 8) | (prefix[2] << 16) | (prefix[3] << 24); // Actually, the bytes store segmentCount - 1. ++segmentCount; if (segmentCount > 65536) { // While technically possible, this is so implausible that we should mark it impossible. // This helps to make sure we fail fast on packed input. return IMPOSSIBLE; } else if (segmentCount > 256) { // Implausible segment count. return IMPLAUSIBLE; } uint32_t segment0Size = prefix[4] | (prefix[5] << 8) | (prefix[6] << 16) | (prefix[7] << 24); if (segment0Size > (1 << 27)) { // Segment larger than 1G seems implausible. return IMPLAUSIBLE; } uint32_t segment0Offset = 4 + segmentCount * 4; if (segment0Offset % 8 != 0) { segment0Offset += 4; } KJ_ASSERT(segment0Offset % 8 == 0); if (prefix.size() < segment0Offset + 8) { // Segment 0 is past our prefix, so we can't check it. return PLAUSIBLE; } return isPlausiblyFlat(prefix.slice(segment0Offset, prefix.size()), segmentCount); } Plausibility isPlausiblyPacked(kj::ArrayPtr prefix, kj::Function)> checkUnpacked) { kj::Vector unpacked; // Try to unpack a prefix so that we can check it. const byte* pos = prefix.begin(); const byte* end = prefix.end(); if (end - pos > 1024) { // Don't bother unpacking more than 1k. end = pos + 1024; } while (pos < end) { byte tag = *pos++; for (uint i = 0; i < 8 && pos < end; i++) { if (tag & (1 << i)) { byte b = *pos++; if (b == 0) { // A zero byte should have been deflated away. return IMPOSSIBLE; } unpacked.add(b); } else { unpacked.add(0); } } if (pos == end) { break; } if (tag == 0) { uint count = *pos++ * 8; unpacked.addAll(kj::repeat(byte(0), count)); } else if (tag == 0xff) { uint count = *pos++ * 8; size_t available = end - pos; uint n = kj::min(count, available); unpacked.addAll(pos, pos + n); pos += n; } } return checkUnpacked(unpacked); } Plausibility isPlausiblyPacked(kj::ArrayPtr prefix) { return isPlausiblyPacked(prefix, KJ_BIND_METHOD(*this, isPlausiblyBinary)); } Plausibility isPlausiblyPackedFlat(kj::ArrayPtr prefix) { return isPlausiblyPacked(prefix, [this](kj::ArrayPtr prefix) { return isPlausiblyFlat(prefix); }); } Plausibility isPlausiblyText(kj::ArrayPtr prefix) { enum { PREAMBLE, COMMENT, BODY } state = PREAMBLE; for (char c: prefix.asChars()) { switch (state) { case PREAMBLE: // Before opening parenthesis. switch (c) { case '(': state = BODY; continue; case '#': state = COMMENT; continue; case ' ': case '\n': case '\r': case '\t': case '\v': // whitespace break; default: // Not whitespace, not comment, not open parenthesis. Impossible! return IMPOSSIBLE; } break; case COMMENT: switch (c) { case '\n': state = PREAMBLE; continue; default: break; } break; case BODY: switch (c) { case '\"': case '\'': // String literal. Let's stop here before things get complicated. return PLAUSIBLE; default: break; } break; } if ((static_cast(c) < 0x20 && c != '\n' && c != '\r' && c != '\t' && c != '\v') || c == 0x7f) { // Unprintable character. return IMPOSSIBLE; } } return PLAUSIBLE; } Plausibility isPlausiblyJson(kj::ArrayPtr prefix) { enum { PREAMBLE, COMMENT, BODY } state = PREAMBLE; for (char c: prefix.asChars()) { switch (state) { case PREAMBLE: // Before opening parenthesis. switch (c) { case '{': state = BODY; continue; case '#': state = COMMENT; continue; case '/': state = COMMENT; continue; case ' ': case '\n': case '\r': case '\t': case '\v': // whitespace break; default: // Not whitespace, not comment, not open brace. Impossible! return IMPOSSIBLE; } break; case COMMENT: switch (c) { case '\n': state = PREAMBLE; continue; default: break; } break; case BODY: switch (c) { case '\"': // String literal. Let's stop here before things get complicated. return PLAUSIBLE; default: break; } break; } if ((c > 0 && c < ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\v') || c == 0x7f) { // Unprintable character. return IMPOSSIBLE; } } return PLAUSIBLE; } Plausibility isPlausibly(Format format, kj::ArrayPtr prefix) { switch (format) { case Format::BINARY : return isPlausiblyBinary (prefix); case Format::PACKED : return isPlausiblyPacked (prefix); case Format::FLAT : return isPlausiblyFlat (prefix); case Format::FLAT_PACKED: return isPlausiblyPackedFlat(prefix); case Format::CANONICAL : return isPlausiblyFlat (prefix); case Format::TEXT : return isPlausiblyText (prefix); case Format::JSON : return isPlausiblyJson (prefix); } KJ_UNREACHABLE; } kj::Maybe guessFormat(kj::ArrayPtr prefix) { Format candidates[] = { Format::BINARY, Format::TEXT, Format::PACKED, Format::JSON, Format::FLAT, Format::FLAT_PACKED }; for (Format candidate: candidates) { if (plausibleOrWrongType(isPlausibly(candidate, prefix))) { return candidate; } } return nullptr; } kj::MainBuilder::Validity checkPlausibility(Format format, kj::ArrayPtr prefix) { switch (isPlausibly(format, prefix)) { case PLAUSIBLE: return true; case IMPOSSIBLE: KJ_IF_MAYBE(guess, guessFormat(prefix)) { return kj::str( "The input is not in \"", toString(format), "\" format. It looks like it is in \"", toString(*guess), "\" format. Try that instead."); } else { return kj::str( "The input is not in \"", toString(format), "\" format."); } case IMPLAUSIBLE: KJ_IF_MAYBE(guess, guessFormat(prefix)) { context.warning(kj::str( "*** WARNING ***\n" "The input data does not appear to be in \"", toString(format), "\" format. It\n" "looks like it may be in \"", toString(*guess), "\" format. I'll try to parse\n" "it in \"", toString(format), "\" format as you requested, but if it doesn't work,\n" "try \"", toString(format), "\" instead. Use --quiet to suppress this warning.\n" "*** END WARNING ***\n")); } else { context.warning(kj::str( "*** WARNING ***\n" "The input data does not appear to be in \"", toString(format), "\" format, nor\n" "in any other known format. I'll try to parse it in \"", toString(format), "\"\n" "format anyway, as you requested. Use --quiet to suppress this warning.\n" "*** END WARNING ***\n")); } return true; case WRONG_TYPE: if (format == Format::FLAT && plausibleOrWrongType(isPlausiblyBinary(prefix))) { context.warning( "*** WARNING ***\n" "The input data does not appear to match the schema that you specified. I'll try\n" "to parse it anyway, but if it doesn't look right, please verify that you\n" "have the right schema. This could also be because the input is not in \"flat\"\n" "format; indeed, it looks like this input may be in regular binary format,\n" "so you might want to try \"binary\" instead. Use --quiet to suppress this\n" "warning.\n" "*** END WARNING ***\n"); } else if (format == Format::FLAT_PACKED && plausibleOrWrongType(isPlausiblyPacked(prefix))) { context.warning( "*** WARNING ***\n" "The input data does not appear to match the schema that you specified. I'll try\n" "to parse it anyway, but if it doesn't look right, please verify that you\n" "have the right schema. This could also be because the input is not in \"flat-packed\"\n" "format; indeed, it looks like this input may be in regular packed format,\n" "so you might want to try \"packed\" instead. Use --quiet to suppress this\n" "warning.\n" "*** END WARNING ***\n"); } else { context.warning( "*** WARNING ***\n" "The input data does not appear to be the type that you specified. I'll try\n" "to parse it anyway, but if it doesn't look right, please verify that you\n" "have the right type. Use --quiet to suppress this warning.\n" "*** END WARNING ***\n"); } return true; } KJ_UNREACHABLE; } public: // ----------------------------------------------------------------- kj::MainBuilder::Validity encode() { convertFrom = Format::TEXT; convertTo = formatFromDeprecatedFlags(Format::BINARY); return convert(); } kj::MainBuilder::Validity setEvalOutputFormat(kj::StringPtr format) { KJ_IF_MAYBE(f, parseFormatName(format)) { convertTo = *f; return true; } else { return kj::str("unknown format: ", format); } } kj::MainBuilder::Validity evalConst(kj::StringPtr name) { convertTo = formatFromDeprecatedFlags(convertTo); KJ_ASSERT(sourceFiles.size() == 1); auto parser = kj::parse::sequence( kj::parse::many( kj::parse::sequence( kj::parse::identifier, kj::parse::many( kj::parse::sequence( kj::parse::exactChar<'['>(), kj::parse::integer, kj::parse::exactChar<']'>())), kj::parse::oneOf( kj::parse::endOfInput, kj::parse::sequence( kj::parse::exactChar<'.'>(), kj::parse::notLookingAt(kj::parse::endOfInput))))), kj::parse::endOfInput); kj::parse::IteratorInput input(name.begin(), name.end()); kj::Array>> nameParts; KJ_IF_MAYBE(p, parser(input)) { nameParts = kj::mv(*p); } else { return "invalid syntax"; } auto pos = nameParts.begin(); // Traverse the path to find a schema. uint64_t scopeId = sourceFiles[0].id; bool stoppedAtSubscript = false; for (; pos != nameParts.end(); ++pos) { kj::StringPtr part = kj::get<0>(*pos); KJ_IF_MAYBE(childId, compiler->lookup(scopeId, part)) { scopeId = *childId; if (kj::get<1>(*pos).size() > 0) { stoppedAtSubscript = true; break; } } else { break; } } Schema schema = compiler->getLoader().get(scopeId); // Evaluate this schema to a DynamicValue. DynamicValue::Reader value; word zeroWord[1]; memset(&zeroWord, 0, sizeof(zeroWord)); kj::ArrayPtr segments[1] = { kj::arrayPtr(zeroWord, 1) }; SegmentArrayMessageReader emptyMessage(segments); switch (schema.getProto().which()) { case schema::Node::CONST: value = schema.asConst(); break; case schema::Node::STRUCT: if (pos == nameParts.end()) { return kj::str("'", schema.getShortDisplayName(), "' cannot be evaluated."); } // Use the struct's default value. value = emptyMessage.getRoot(schema.asStruct()); break; default: if (stoppedAtSubscript) { return kj::str("'", schema.getShortDisplayName(), "' is not a list."); } else if (pos != nameParts.end()) { return kj::str("'", kj::get<0>(*pos), "' is not defined."); } else { return kj::str("'", schema.getShortDisplayName(), "' cannot be evaluated."); } } // Traverse the rest of the path as struct fields. for (; pos != nameParts.end(); ++pos) { kj::StringPtr partName = kj::get<0>(*pos); if (!stoppedAtSubscript) { if (value.getType() == DynamicValue::STRUCT) { auto structValue = value.as(); KJ_IF_MAYBE(field, structValue.getSchema().findFieldByName(partName)) { value = structValue.get(*field); } else { return kj::str("'", kj::get<0>(pos[-1]), "' has no member '", partName, "'."); } } else { return kj::str("'", kj::get<0>(pos[-1]), "' is not a struct."); } } auto& subscripts = kj::get<1>(*pos); for (uint i = 0; i < subscripts.size(); i++) { uint64_t subscript = subscripts[i]; if (value.getType() == DynamicValue::LIST) { auto listValue = value.as(); if (subscript < listValue.size()) { value = listValue[subscript]; } else { return kj::str("'", partName, "[", kj::strArray(subscripts.slice(0, i + 1), "]["), "]' is out-of-bounds."); } } else { if (i > 0) { return kj::str("'", partName, "[", kj::strArray(subscripts.slice(0, i), "]["), "]' is not a list."); } else { return kj::str("'", partName, "' is not a list."); } } } stoppedAtSubscript = false; } // OK, we have a value. Print it. if (convertTo != Format::TEXT) { if (value.getType() != DynamicValue::STRUCT) { return "not a struct; binary output is only available on structs"; } auto structValue = value.as(); rootType = structValue.getSchema(); kj::FdOutputStream output(STDOUT_FILENO); writeConversion(structValue, output); context.exit(); } else { if (pretty && value.getType() == DynamicValue::STRUCT) { context.exitInfo(prettyPrint(value.as()).flatten()); } else if (pretty && value.getType() == DynamicValue::LIST) { context.exitInfo(prettyPrint(value.as()).flatten()); } else { context.exitInfo(kj::str(value)); } } KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT; } public: // ===================================================================================== void addError(const kj::ReadableDirectory& directory, kj::PathPtr path, SourcePos start, SourcePos end, kj::StringPtr message) override { auto file = getDisplayName(directory, path); kj::String wholeMessage; if (end.line == start.line) { if (end.column == start.column) { wholeMessage = kj::str(file, ":", start.line + 1, ":", start.column + 1, ": error: ", message, "\n"); } else { wholeMessage = kj::str(file, ":", start.line + 1, ":", start.column + 1, "-", end.column + 1, ": error: ", message, "\n"); } } else { // The error spans multiple lines, so just report it on the first such line. wholeMessage = kj::str(file, ":", start.line + 1, ": error: ", message, "\n"); } context.error(wholeMessage); hadErrors_ = true; } bool hadErrors() override { return hadErrors_; } private: kj::ProcessContext& context; kj::Own disk; ModuleLoader loader; kj::SpaceFor compilerSpace; bool compilerConstructed = false; kj::Own compiler; Compiler::AnnotationFlag annotationFlag = Compiler::COMPILE_ANNOTATIONS; uint compileEagerness = Compiler::NODE | Compiler::CHILDREN | Compiler::DEPENDENCIES | Compiler::DEPENDENCY_PARENTS; // By default we compile each explicitly listed schema in full, plus first-level dependencies // of those schemas, plus the parent nodes of any dependencies. This is what most code generators // require to function. struct SourceDirectory { kj::Own dir; bool isSourcePrefix; }; kj::HashMap sourceDirectories; // For each import path and source prefix, tracks the directory object we opened for it. // // Use via getSourceDirectory(). kj::HashMap dirPrefixes; // For each open directory object, maps to a path prefix to add when displaying this path in // error messages. This keeps track of the original directory name as given by the user, before // canonicalization. // // Use via getDisplayName(). bool addStandardImportPaths = true; Format convertFrom = Format::BINARY; Format convertTo = Format::BINARY; // For the "convert" command. bool binary = false; bool flat = false; bool packed = false; bool pretty = true; bool quiet = false; uint segmentSize = 0; StructSchema rootType; // For the "decode" and "encode" commands. struct SourceFile { uint64_t id; Compiler::ModuleScope compiled; kj::StringPtr name; Module* module; }; kj::Vector sourceFiles; struct OutputDirective { kj::ArrayPtr name; kj::Maybe dir; KJ_DISALLOW_COPY(OutputDirective); OutputDirective(OutputDirective&&) = default; OutputDirective(kj::ArrayPtr name, kj::Maybe dir) : name(name), dir(kj::mv(dir)) {} }; kj::Vector outputs; bool hadErrors_ = false; kj::Maybe getSourceDirectory( kj::StringPtr pathStr, bool isSourcePrefix) { auto cwd = disk->getCurrentPath(); auto path = cwd.evalNative(pathStr); if (path.size() == 0) return disk->getRoot(); KJ_IF_MAYBE(sdir, sourceDirectories.find(path)) { sdir->isSourcePrefix = sdir->isSourcePrefix || isSourcePrefix; return *sdir->dir; } if (path == cwd) { // Slight hack if the working directory is explicitly specified: // - We want to avoid opening a new copy of the working directory, as tryOpenSubdir() would // do. // - If isSourcePrefix is true, we need to add it to sourceDirectories to track that. // Otherwise we don't need to add it at all. // - We do not need to add it to dirPrefixes since the cwd is already handled in // getDisplayName(). auto& result = disk->getCurrent(); if (isSourcePrefix) { kj::Own fakeOwn(&result, kj::NullDisposer::instance); sourceDirectories.insert(kj::mv(path), { kj::mv(fakeOwn), isSourcePrefix }); } return result; } KJ_IF_MAYBE(dir, disk->getRoot().tryOpenSubdir(path)) { auto& result = *dir->get(); sourceDirectories.insert(kj::mv(path), { kj::mv(*dir), isSourcePrefix }); #if _WIN32 kj::String prefix = pathStr.endsWith("/") || pathStr.endsWith("\\") ? kj::str(pathStr) : kj::str(pathStr, '\\'); #else kj::String prefix = pathStr.endsWith("/") ? kj::str(pathStr) : kj::str(pathStr, '/'); #endif dirPrefixes.insert(&result, kj::mv(prefix)); return result; } else { return nullptr; } } struct DirPathPair { const kj::ReadableDirectory& dir; kj::Path path; }; DirPathPair interpretSourceFile(kj::StringPtr pathStr) { auto cwd = disk->getCurrentPath(); auto path = cwd.evalNative(pathStr); KJ_REQUIRE(path.size() > 0); for (size_t i = path.size() - 1; i > 0; i--) { auto prefix = path.slice(0, i); auto remainder = path.slice(i, path.size()); KJ_IF_MAYBE(sdir, sourceDirectories.find(prefix)) { if (sdir->isSourcePrefix) { return { *sdir->dir, remainder.clone() }; } } } // No source prefix matched. Fall back to heuristic: try stripping the current directory, // otherwise don't strip anything. if (path.startsWith(cwd)) { return { disk->getCurrent(), path.slice(cwd.size(), path.size()).clone() }; } else { // Hmm, no src-prefix matched and the file isn't even in the current directory. This might // be OK if we aren't generating any output anyway, but otherwise the results will almost // certainly not be what the user wanted. Let's print a warning, unless the output directives // are ones which we know do not produce output files. This is a hack. for (auto& output: outputs) { auto name = kj::str(output.name); if (name != "-" && name != "capnp") { context.warning(kj::str(pathStr, ": File is not in the current directory and does not match any prefix defined with " "--src-prefix. Please pass an appropriate --src-prefix so I can figure out where to " "write the output for this file.")); break; } } return { disk->getRoot(), kj::mv(path) }; } } kj::String getDisplayName(const kj::ReadableDirectory& dir, kj::PathPtr path) { KJ_IF_MAYBE(prefix, dirPrefixes.find(&dir)) { return kj::str(*prefix, path.toNativeString()); } else if (&dir == &disk->getRoot()) { return path.toNativeString(true); } else if (&dir == &disk->getCurrent()) { return path.toNativeString(false); } else { KJ_FAIL_ASSERT("unrecognized directory"); } } }; } // namespace compiler } // namespace capnp KJ_MAIN(capnp::compiler::CompilerMain); capnproto-c++-1.1.0/src/capnp/compiler/resolver.h0000644000175000017500000001361714712011043022457 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2020 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include CAPNP_BEGIN_HEADER namespace capnp { namespace compiler { class Resolver { // Callback class used to find other nodes relative to some existing node. // // `Resolver` is used when compiling one declaration requires inspecting the compiled versions // of other declarations it depends on. For example, if struct type Foo contains a field of type // Bar, and specifies a default value for that field, then to parse that default value we need // the compiled version of `Bar`. Or, more commonly, if a struct type Foo refers to some other // type `Bar.Baz`, this requires doing a lookup that depends on at least partial compilation of // `Bar`, in order to discover its nested type `Baz`. // // Note that declarations are often compiled just-in-time the first time they are resolved. So, // the methods of Resolver may recurse back into other parts of the compiler. It must detect when // a dependency cycle occurs and report an error in order to prevent an infinite loop. public: struct ResolvedDecl { // Information about a resolved declaration. uint64_t id; // Type ID / node ID of the resolved declaration. uint genericParamCount; // If non-zero, the declaration is a generic with the given number of parameters. uint64_t scopeId; // The ID of the parent scope of this declaration. Declaration::Which kind; // What basic kind of declaration is this? E.g. struct, interface, const, etc. Resolver* resolver; // `Resolver` instance that can be used to further resolve other declarations relative to this // one. kj::Maybe brand; // If present, then it is necessary to replace the brand scope with the given brand before // using the target type. This happens when the decl resolved to an alias; all other fields // of `ResolvedDecl` refer to the target of the alias, except for `scopeId` which is the // scope that contained the alias. }; struct ResolvedParameter { uint64_t id; // ID of the node declaring the parameter. uint index; // Index of the parameter. }; typedef kj::OneOf ResolveResult; virtual kj::Maybe resolve(kj::StringPtr name) = 0; // Look up the given name, relative to this node, and return basic information about the // target. virtual kj::Maybe resolveMember(kj::StringPtr name) = 0; // Look up a member of this node. virtual ResolvedDecl resolveBuiltin(Declaration::Which which) = 0; virtual ResolvedDecl resolveId(uint64_t id) = 0; virtual kj::Maybe getParent() = 0; // Returns the parent of this scope, or null if this is the top scope. virtual ResolvedDecl getTopScope() = 0; // Get the top-level scope containing this node. virtual kj::Maybe resolveBootstrapSchema(uint64_t id, schema::Brand::Reader brand) = 0; // Get the schema for the given ID. If a schema is returned, it must be safe to traverse its // dependencies via the Schema API. A schema that is only at the bootstrap stage is // acceptable. // // Throws an exception if the id is not one that was found by calling resolve() or by // traversing other schemas. Returns null if the ID is recognized, but the corresponding // schema node failed to be built for reasons that were already reported. virtual kj::Maybe resolveFinalSchema(uint64_t id) = 0; // Get the final schema for the given ID. A bootstrap schema is not acceptable. A raw // node reader is returned rather than a Schema object because using a Schema object built // by the final schema loader could trigger lazy initialization of dependencies which could // lead to a cycle and deadlock. // // Throws an exception if the id is not one that was found by calling resolve() or by // traversing other schemas. Returns null if the ID is recognized, but the corresponding // schema node failed to be built for reasons that were already reported. virtual kj::Maybe resolveImport(kj::StringPtr name) = 0; // Get the ID of an imported file given the import path. virtual kj::Maybe> readEmbed(kj::StringPtr name) = 0; // Read and return the contents of a file for an `embed` expression. virtual kj::Maybe resolveBootstrapType(schema::Type::Reader type, Schema scope) = 0; // Compile a schema::Type into a Type whose dependencies may safely be traversed via the schema // API. These dependencies may have only bootstrap schemas. Returns null if the type could not // be constructed due to already-reported errors. }; } // namespace compiler } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/serialize-packed.h0000644000175000017500000001240714712011043022214 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "serialize.h" CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private class PackedInputStream: public kj::InputStream { // An input stream that unpacks packed data with a picky constraint: The caller must read data // in the exact same size and sequence as the data was written to PackedOutputStream. public: explicit PackedInputStream(kj::BufferedInputStream& inner); KJ_DISALLOW_COPY_AND_MOVE(PackedInputStream); ~PackedInputStream() noexcept(false); // implements InputStream ------------------------------------------ size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override; void skip(size_t bytes) override; private: kj::BufferedInputStream& inner; }; class PackedOutputStream: public kj::OutputStream { // An output stream that packs data. Buffers passed to `write()` must be word-aligned. public: explicit PackedOutputStream(kj::BufferedOutputStream& inner); KJ_DISALLOW_COPY_AND_MOVE(PackedOutputStream); ~PackedOutputStream() noexcept(false); // implements OutputStream ----------------------------------------- void write(const void* buffer, size_t bytes) override; private: kj::BufferedOutputStream& inner; }; } // namespace _ (private) class PackedMessageReader: private _::PackedInputStream, public InputStreamMessageReader { public: PackedMessageReader(kj::BufferedInputStream& inputStream, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); KJ_DISALLOW_COPY_AND_MOVE(PackedMessageReader); ~PackedMessageReader() noexcept(false); }; class PackedFdMessageReader: private kj::FdInputStream, private kj::BufferedInputStreamWrapper, public PackedMessageReader { public: PackedFdMessageReader(int fd, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Read message from a file descriptor, without taking ownership of the descriptor. // Note that if you want to reuse the descriptor after the reader is destroyed, you'll need to // seek it, since otherwise the position is unspecified. PackedFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Read a message from a file descriptor, taking ownership of the descriptor. KJ_DISALLOW_COPY_AND_MOVE(PackedFdMessageReader); ~PackedFdMessageReader() noexcept(false); }; void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder); void writePackedMessage(kj::BufferedOutputStream& output, kj::ArrayPtr> segments); // Write a packed message to a buffered output stream. void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder); void writePackedMessage(kj::OutputStream& output, kj::ArrayPtr> segments); // Write a packed message to an unbuffered output stream. If you intend to write multiple messages // in succession, consider wrapping your output in a buffered stream in order to reduce system // call overhead. void writePackedMessageToFd(int fd, MessageBuilder& builder); void writePackedMessageToFd(int fd, kj::ArrayPtr> segments); // Write a single packed message to the file descriptor. size_t computeUnpackedSizeInWords(kj::ArrayPtr packedBytes); // Computes the number of words to which the given packed bytes will unpack. Not intended for use // in performance-sensitive situations. // ======================================================================================= // inline stuff inline void writePackedMessage(kj::BufferedOutputStream& output, MessageBuilder& builder) { writePackedMessage(output, builder.getSegmentsForOutput()); } inline void writePackedMessage(kj::OutputStream& output, MessageBuilder& builder) { writePackedMessage(output, builder.getSegmentsForOutput()); } inline void writePackedMessageToFd(int fd, MessageBuilder& builder) { writePackedMessageToFd(fd, builder.getSegmentsForOutput()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/message.c++0000644000175000017500000002521414712011043020545 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "message.h" #include #include "arena.h" #include "orphan.h" #include #include namespace capnp { namespace { class DummyCapTableReader: public _::CapTableReader { public: kj::Maybe> extractCap(uint index) override { #if CAPNP_LITE KJ_UNIMPLEMENTED("no cap tables in lite mode"); #else return nullptr; #endif } }; static KJ_CONSTEXPR(const) DummyCapTableReader dummyCapTableReader = DummyCapTableReader(); } // namespace MessageReader::MessageReader(ReaderOptions options): options(options), allocatedArena(false) {} MessageReader::~MessageReader() noexcept(false) { if (allocatedArena) { arena()->~ReaderArena(); } } bool MessageReader::isCanonical() { if (!allocatedArena) { static_assert(sizeof(_::ReaderArena) <= sizeof(arenaSpace), "arenaSpace is too small to hold a ReaderArena. Please increase it. This will break " "ABI compatibility."); kj::ctor(*arena(), this); allocatedArena = true; } _::SegmentReader *segment = arena()->tryGetSegment(_::SegmentId(0)); if (segment == NULL) { // The message has no segments return false; } if (arena()->tryGetSegment(_::SegmentId(1))) { // The message has more than one segment return false; } const word* readHead = segment->getStartPtr() + 1; bool rootIsCanonical = _::PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), this->getOptions().nestingLimit) .isCanonical(&readHead); bool allWordsConsumed = segment->getOffsetTo(readHead) == segment->getSize(); return rootIsCanonical && allWordsConsumed; } size_t MessageReader::sizeInWords() { return arena()->sizeInWords(); } AnyPointer::Reader MessageReader::getRootInternal() { if (!allocatedArena) { static_assert(sizeof(_::ReaderArena) <= sizeof(arenaSpace), "arenaSpace is too small to hold a ReaderArena. Please increase it. This will break " "ABI compatibility."); kj::ctor(*arena(), this); allocatedArena = true; } _::SegmentReader* segment = arena()->tryGetSegment(_::SegmentId(0)); KJ_REQUIRE(segment != nullptr && segment->checkObject(segment->getStartPtr(), ONE * WORDS), "Message did not contain a root pointer.") { return AnyPointer::Reader(); } // const_cast here is safe because dummyCapTableReader has no state. return AnyPointer::Reader(_::PointerReader::getRoot( segment, const_cast(&dummyCapTableReader), segment->getStartPtr(), options.nestingLimit)); } // ------------------------------------------------------------------- MessageBuilder::MessageBuilder(): allocatedArena(false) {} MessageBuilder::~MessageBuilder() noexcept(false) { if (allocatedArena) { kj::dtor(*arena()); } } MessageBuilder::MessageBuilder(kj::ArrayPtr segments) : allocatedArena(false) { kj::ctor(*arena(), this, segments); allocatedArena = true; } _::SegmentBuilder* MessageBuilder::getRootSegment() { if (allocatedArena) { return arena()->getSegment(_::SegmentId(0)); } else { static_assert(sizeof(_::BuilderArena) <= sizeof(arenaSpace), "arenaSpace is too small to hold a BuilderArena. Please increase it."); kj::ctor(*arena(), this); allocatedArena = true; auto allocation = arena()->allocate(POINTER_SIZE_IN_WORDS); KJ_ASSERT(allocation.segment->getSegmentId() == _::SegmentId(0), "First allocated word of new arena was not in segment ID 0."); KJ_ASSERT(allocation.words == allocation.segment->getPtrUnchecked(ZERO * WORDS), "First allocated word of new arena was not the first word in its segment."); return allocation.segment; } } AnyPointer::Builder MessageBuilder::getRootInternal() { _::SegmentBuilder* rootSegment = getRootSegment(); return AnyPointer::Builder(_::PointerBuilder::getRoot( rootSegment, arena()->getLocalCapTable(), rootSegment->getPtrUnchecked(ZERO * WORDS))); } kj::ArrayPtr> MessageBuilder::getSegmentsForOutput() { if (allocatedArena) { return arena()->getSegmentsForOutput(); } else { return nullptr; } } Orphanage MessageBuilder::getOrphanage() { // We must ensure that the arena and root pointer have been allocated before the Orphanage // can be used. if (!allocatedArena) getRootSegment(); return Orphanage(arena(), arena()->getLocalCapTable()); } bool MessageBuilder::isCanonical() { _::SegmentReader *segment = getRootSegment(); if (segment == NULL) { // The message has no segments return false; } if (arena()->tryGetSegment(_::SegmentId(1))) { // The message has more than one segment return false; } const word* readHead = segment->getStartPtr() + 1; return _::PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), kj::maxValue) .isCanonical(&readHead); } size_t MessageBuilder::sizeInWords() { return arena()->sizeInWords(); } kj::Own<_::CapTableBuilder> MessageBuilder::releaseBuiltinCapTable() { return arena()->releaseLocalCapTable(); } // ======================================================================================= SegmentArrayMessageReader::SegmentArrayMessageReader( kj::ArrayPtr> segments, ReaderOptions options) : MessageReader(options), segments(segments) {} SegmentArrayMessageReader::~SegmentArrayMessageReader() noexcept(false) {} kj::ArrayPtr SegmentArrayMessageReader::getSegment(uint id) { if (id < segments.size()) { return segments[id]; } else { return nullptr; } } // ------------------------------------------------------------------- MallocMessageBuilder::MallocMessageBuilder( uint firstSegmentWords, AllocationStrategy allocationStrategy) : nextSize(firstSegmentWords), allocationStrategy(allocationStrategy), ownFirstSegment(true), returnedFirstSegment(false), firstSegment(nullptr) {} MallocMessageBuilder::MallocMessageBuilder( kj::ArrayPtr firstSegment, AllocationStrategy allocationStrategy) : nextSize(firstSegment.size()), allocationStrategy(allocationStrategy), ownFirstSegment(false), returnedFirstSegment(false), firstSegment(firstSegment.begin()) { KJ_REQUIRE(firstSegment.size() > 0, "First segment size must be non-zero."); // Checking just the first word should catch most cases of failing to zero the segment. KJ_REQUIRE(*reinterpret_cast(firstSegment.begin()) == 0, "First segment must be zeroed."); } MallocMessageBuilder::~MallocMessageBuilder() noexcept(false) { if (returnedFirstSegment) { if (ownFirstSegment) { free(firstSegment); } else { // Must zero first segment. kj::ArrayPtr> segments = getSegmentsForOutput(); if (segments.size() > 0) { KJ_ASSERT(segments[0].begin() == firstSegment, "First segment in getSegmentsForOutput() is not the first segment allocated?"); memset(firstSegment, 0, segments[0].size() * sizeof(word)); } } for (void* ptr: moreSegments) { free(ptr); } } } kj::ArrayPtr MallocMessageBuilder::allocateSegment(uint minimumSize) { KJ_REQUIRE(bounded(minimumSize) * WORDS <= MAX_SEGMENT_WORDS, "MallocMessageBuilder asked to allocate segment above maximum serializable size."); KJ_ASSERT(bounded(nextSize) * WORDS <= MAX_SEGMENT_WORDS, "MallocMessageBuilder nextSize out of bounds."); if (!returnedFirstSegment && !ownFirstSegment) { kj::ArrayPtr result = kj::arrayPtr(reinterpret_cast(firstSegment), nextSize); if (result.size() >= minimumSize) { returnedFirstSegment = true; return result; } // If the provided first segment wasn't big enough, we discard it and proceed to allocate // our own. This never happens in practice since minimumSize is always 1 for the first // segment. ownFirstSegment = true; } uint size = kj::max(minimumSize, nextSize); void* result = calloc(size, sizeof(word)); if (result == nullptr) { KJ_FAIL_SYSCALL("calloc(size, sizeof(word))", ENOMEM, size); } if (!returnedFirstSegment) { firstSegment = result; returnedFirstSegment = true; // After the first segment, we want nextSize to equal the total size allocated so far. if (allocationStrategy == AllocationStrategy::GROW_HEURISTICALLY) nextSize = size; } else { moreSegments.add(result); if (allocationStrategy == AllocationStrategy::GROW_HEURISTICALLY) { // set nextSize = min(nextSize+size, MAX_SEGMENT_WORDS) // while protecting against possible overflow of (nextSize+size) nextSize = (size <= unbound(MAX_SEGMENT_WORDS / WORDS) - nextSize) ? nextSize + size : unbound(MAX_SEGMENT_WORDS / WORDS); } } return kj::arrayPtr(reinterpret_cast(result), size); } // ------------------------------------------------------------------- FlatMessageBuilder::FlatMessageBuilder(kj::ArrayPtr array): array(array), allocated(false) {} FlatMessageBuilder::~FlatMessageBuilder() noexcept(false) {} void FlatMessageBuilder::requireFilled() { KJ_REQUIRE(getSegmentsForOutput()[0].end() == array.end(), "FlatMessageBuilder's buffer was too large."); } kj::ArrayPtr FlatMessageBuilder::allocateSegment(uint minimumSize) { KJ_REQUIRE(!allocated, "FlatMessageBuilder's buffer was not large enough."); allocated = true; return array; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/stream.capnp0000644000175000017500000000476114527152321021162 0ustar00kentonkenton00000000000000# Copyright (c) 2019 Cloudflare, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0x86c366a91393f3f8; # Defines placeholder types used to provide backwards-compatibility while introducing streaming # to the language. The goal is that old code generators that don't know about streaming can still # generate code that functions, leaving it up to the application to implement flow control # manually. $import "/capnp/c++.capnp".namespace("capnp"); struct StreamResult @0x995f9a3377c0b16e { # Empty struct that serves as the return type for "streaming" methods. # # Defining a method like: # # write @0 (bytes :Data) -> stream; # # Is equivalent to: # # write @0 (bytes :Data) -> import "/capnp/stream.capnp".StreamResult; # # However, implementations that recognize streaming will elide the reference to StreamResult # and instead give write() a different signature appropriate for streaming. # # Streaming methods do not return a result -- that is, they return Promise. This promise # resolves not to indicate that the call was actually delivered, but instead to provide # backpressure. When the previous call's promise resolves, it is time to make another call. On # the client side, the RPC system will resolve promises immediately until an appropriate number # of requests are in-flight, and then will delay promise resolution to apply back-pressure. # On the server side, the RPC system will deliver one call at a time. } capnproto-c++-1.1.0/src/capnp/blob.h0000644000175000017500000002047414731420004017723 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include "common.h" #include CAPNP_BEGIN_HEADER namespace capnp { struct Data { Data() = delete; class Reader; class Builder; class Pipeline {}; }; struct Text { Text() = delete; class Reader; class Builder; class Pipeline {}; }; class Data::Reader: public kj::ArrayPtr { // Points to a blob of bytes. The usual Reader rules apply -- Data::Reader behaves like a simple // pointer which does not own its target, can be passed by value, etc. public: typedef Data Reads; Reader() = default; inline Reader(decltype(nullptr)): ArrayPtr(nullptr) {} inline Reader(const byte* value, size_t size): ArrayPtr(value, size) {} inline Reader(const kj::Array& value): ArrayPtr(value) {} inline Reader(const ArrayPtr& value): ArrayPtr(value) {} inline Reader(const kj::Array& value): ArrayPtr(value) {} inline Reader(const ArrayPtr& value): ArrayPtr(value) {} }; class Text::Reader: public kj::StringPtr { // Like Data::Reader, but points at NUL-terminated UTF-8 text. The NUL terminator is not counted // in the size but must be present immediately after the last byte. // // Text::Reader's interface contract is that its data MUST be NUL-terminated. The producer of // the Text::Reader must guarantee this, so that the consumer need not check. The data SHOULD // also be valid UTF-8, but this is NOT guaranteed -- the consumer must verify if it cares. public: typedef Text Reads; Reader() = default; inline Reader(decltype(nullptr)): StringPtr(nullptr) {} inline Reader(const char* value): StringPtr(value) {} inline Reader(const char* value, size_t size): StringPtr(value, size) {} inline Reader(const kj::String& value): StringPtr(value) {} inline Reader(const StringPtr& value): StringPtr(value) {} #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP template < typename T, typename = kj::EnableIf().c_str()), const char*>()>> inline Reader(const T& t): StringPtr(t) {} // Allow implicit conversion from any class that has a c_str() method (namely, std::string). // We use a template trick to detect std::string in order to avoid including the header for // those who don't want it. #endif }; class Data::Builder: public kj::ArrayPtr { // Like Data::Reader except the pointers aren't const. public: typedef Data Builds; Builder() = default; inline Builder(decltype(nullptr)): ArrayPtr(nullptr) {} inline Builder(byte* value, size_t size): ArrayPtr(value, size) {} inline Builder(kj::Array& value): ArrayPtr(value) {} inline Builder(ArrayPtr value): ArrayPtr(value) {} inline Data::Reader asReader() const { return Data::Reader(kj::implicitCast&>(*this)); } inline operator Reader() const { return asReader(); } }; class Text::Builder: public kj::DisallowConstCopy { // Basically identical to kj::StringPtr, except that the contents are non-const. public: inline Builder(): content(nulstr, 1) {} inline Builder(decltype(nullptr)): content(nulstr, 1) {} inline Builder(char* value): content(value, strlen(value) + 1) {} inline Builder(char* value, size_t size): content(value, size + 1) { KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated."); } inline Reader asReader() const { return Reader(content.begin(), content.size() - 1); } inline operator Reader() const { return asReader(); } inline operator kj::ArrayPtr(); inline kj::ArrayPtr asArray(); inline operator kj::ArrayPtr() const; inline kj::ArrayPtr asArray() const; inline kj::ArrayPtr asBytes() { return asArray().asBytes(); } inline kj::ArrayPtr asBytes() const { return asArray().asBytes(); } // Result does not include NUL terminator. inline operator kj::StringPtr() const; inline kj::StringPtr asString() const; inline const char* cStr() const { return content.begin(); } // Returns NUL-terminated string. inline size_t size() const { return content.size() - 1; } // Result does not include NUL terminator. inline char operator[](size_t index) const { return content[index]; } inline char& operator[](size_t index) { return content[index]; } inline char* begin() { return content.begin(); } inline char* end() { return content.end() - 1; } inline const char* begin() const { return content.begin(); } inline const char* end() const { return content.end() - 1; } inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; } inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; } inline bool operator==(Builder other) const { return asString() == other.asString(); } inline bool operator!=(Builder other) const { return asString() != other.asString(); } inline bool operator< (Builder other) const { return asString() < other.asString(); } inline bool operator> (Builder other) const { return asString() > other.asString(); } inline bool operator<=(Builder other) const { return asString() <= other.asString(); } inline bool operator>=(Builder other) const { return asString() >= other.asString(); } inline kj::StringPtr slice(size_t start) const; inline kj::ArrayPtr slice(size_t start, size_t end) const; inline Builder slice(size_t start); inline kj::ArrayPtr slice(size_t start, size_t end); // A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter // version that assumes end = size(). private: inline explicit Builder(kj::ArrayPtr content): content(content) {} kj::ArrayPtr content; static char nulstr[1]; }; inline kj::StringPtr KJ_STRINGIFY(Text::Builder builder) { return builder.asString(); } inline bool operator==(const char* a, const Text::Builder& b) { return b.asString() == a; } inline bool operator!=(const char* a, const Text::Builder& b) { return b.asString() != a; } inline Text::Builder::operator kj::StringPtr() const { return kj::StringPtr(content.begin(), content.size() - 1); } inline kj::StringPtr Text::Builder::asString() const { return kj::StringPtr(content.begin(), content.size() - 1); } inline Text::Builder::operator kj::ArrayPtr() { return content.slice(0, content.size() - 1); } inline kj::ArrayPtr Text::Builder::asArray() { return content.slice(0, content.size() - 1); } inline Text::Builder::operator kj::ArrayPtr() const { return content.slice(0, content.size() - 1); } inline kj::ArrayPtr Text::Builder::asArray() const { return content.slice(0, content.size() - 1); } inline kj::StringPtr Text::Builder::slice(size_t start) const { return asReader().slice(start); } inline kj::ArrayPtr Text::Builder::slice(size_t start, size_t end) const { return content.slice(start, end); } inline Text::Builder Text::Builder::slice(size_t start) { return Text::Builder(content.slice(start, content.size())); } inline kj::ArrayPtr Text::Builder::slice(size_t start, size_t end) { return content.slice(start, end); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/rpc-test.c++0000644000175000017500000015320314731420004020664 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #include "rpc.h" #include "test-util.h" #include "schema.h" #include "serialize.h" #include #include #include #include #include #include // TODO(cleanup): Auto-generate stringification functions for union discriminants. namespace capnp { namespace rpc { inline kj::String KJ_STRINGIFY(Message::Which which) { return kj::str(static_cast(which)); } } // namespace rpc } // namespace capnp namespace capnp { namespace _ { // private namespace { class RpcDumper { // Class which stringifies RPC messages for debugging purposes, including decoding params and // results based on the call's interface and method IDs and extracting cap descriptors. // // TODO(cleanup): Clean this code up and move it to someplace reusable, so it can be used as // a packet inspector / debugging tool for Cap'n Proto network traffic. public: void addSchema(InterfaceSchema schema) { schemas[schema.getProto().getId()] = schema; } enum Sender { CLIENT, SERVER }; kj::String dump(rpc::Message::Reader message, Sender sender) { const char* senderName = sender == CLIENT ? "client" : "server"; switch (message.which()) { case rpc::Message::CALL: { auto call = message.getCall(); auto iter = schemas.find(call.getInterfaceId()); if (iter == schemas.end()) { break; } InterfaceSchema schema = iter->second; auto methods = schema.getMethods(); if (call.getMethodId() >= methods.size()) { break; } InterfaceSchema::Method method = methods[call.getMethodId()]; auto schemaProto = schema.getProto(); auto interfaceName = schemaProto.getDisplayName().slice(schemaProto.getDisplayNamePrefixLength()); auto methodProto = method.getProto(); auto paramType = method.getParamType(); auto resultType = method.getResultType(); if (call.getSendResultsTo().isCaller()) { returnTypes[std::make_pair(sender, call.getQuestionId())] = resultType; } auto payload = call.getParams(); auto params = kj::str(payload.getContent().getAs(paramType)); auto sendResultsTo = call.getSendResultsTo(); return kj::str(senderName, "(", call.getQuestionId(), "): call ", call.getTarget(), " <- ", interfaceName, ".", methodProto.getName(), params, " caps:[", kj::strArray(payload.getCapTable(), ", "), "]", sendResultsTo.isCaller() ? kj::str() : kj::str(" sendResultsTo:", sendResultsTo)); } case rpc::Message::RETURN: { auto ret = message.getReturn(); auto iter = returnTypes.find( std::make_pair(sender == CLIENT ? SERVER : CLIENT, ret.getAnswerId())); if (iter == returnTypes.end()) { break; } auto schema = iter->second; returnTypes.erase(iter); if (ret.which() != rpc::Return::RESULTS) { // Oops, no results returned. We don't check this earlier because we want to make sure // returnTypes.erase() gets a chance to happen. break; } auto payload = ret.getResults(); if (schema.getProto().isStruct()) { auto results = kj::str(payload.getContent().getAs(schema.asStruct())); return kj::str(senderName, "(", ret.getAnswerId(), "): return ", results, " caps:[", kj::strArray(payload.getCapTable(), ", "), "]"); } else if (schema.getProto().isInterface()) { payload.getContent().getAs(schema.asInterface()); return kj::str(senderName, "(", ret.getAnswerId(), "): return cap ", kj::strArray(payload.getCapTable(), ", ")); } else { break; } } case rpc::Message::BOOTSTRAP: { auto restore = message.getBootstrap(); returnTypes[std::make_pair(sender, restore.getQuestionId())] = InterfaceSchema(); return kj::str(senderName, "(", restore.getQuestionId(), "): bootstrap ", restore.getDeprecatedObjectId().getAs()); } default: break; } return kj::str(senderName, ": ", message); } private: std::map schemas; std::map, Schema> returnTypes; }; // ======================================================================================= class TestNetworkAdapter; class TestNetwork { public: TestNetwork() { dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); dumper.addSchema(Schema::from()); } ~TestNetwork() noexcept(false); TestNetworkAdapter& add(kj::StringPtr name); kj::Maybe find(kj::StringPtr name) { auto iter = map.find(name); if (iter == map.end()) { return nullptr; } else { return *iter->second; } } RpcDumper dumper; private: std::map> map; }; typedef VatNetwork< test::TestSturdyRefHostId, test::TestProvisionId, test::TestRecipientId, test::TestThirdPartyCapId, test::TestJoinResult> TestNetworkAdapterBase; class TestNetworkAdapter final: public TestNetworkAdapterBase { public: TestNetworkAdapter(TestNetwork& network, kj::StringPtr self): network(network), self(self) {} ~TestNetworkAdapter() { kj::Exception exception = KJ_EXCEPTION(FAILED, "Network was destroyed."); for (auto& entry: connections) { entry.second->disconnect(kj::cp(exception)); } } uint getSentCount() { return sent; } uint getReceivedCount() { return received; } void onSend(kj::Function callback) { // Invokes the given callback every time a message is sent. Callback can return false to cause // send() to do nothing. sendCallback = kj::mv(callback); } typedef TestNetworkAdapterBase::Connection Connection; class ConnectionImpl final : public Connection, public kj::Refcounted, public kj::TaskSet::ErrorHandler { public: ConnectionImpl(TestNetworkAdapter& network, RpcDumper::Sender sender) : network(network), sender(sender), tasks(kj::heap(*this)) {} void attach(ConnectionImpl& other) { KJ_REQUIRE(partner == nullptr); KJ_REQUIRE(other.partner == nullptr); partner = other; other.partner = *this; } void disconnect(kj::Exception&& exception) { while (!fulfillers.empty()) { fulfillers.front()->reject(kj::cp(exception)); fulfillers.pop(); } networkException = kj::mv(exception); tasks = nullptr; } class IncomingRpcMessageImpl final: public IncomingRpcMessage, public kj::Refcounted { public: IncomingRpcMessageImpl(kj::Array data) : data(kj::mv(data)), message(this->data) {} AnyPointer::Reader getBody() override { return message.getRoot(); } size_t sizeInWords() override { return data.size(); } kj::Array data; FlatArrayMessageReader message; }; class OutgoingRpcMessageImpl final: public OutgoingRpcMessage { public: OutgoingRpcMessageImpl(ConnectionImpl& connection, uint firstSegmentWordSize) : connection(connection), message(firstSegmentWordSize == 0 ? SUGGESTED_FIRST_SEGMENT_WORDS : firstSegmentWordSize) {} AnyPointer::Builder getBody() override { return message.getRoot(); } void send() override { if (!connection.network.sendCallback(message)) return; if (connection.networkException != nullptr) { return; } ++connection.network.sent; // Uncomment to get a debug dump. // kj::String msg = connection.network.network.dumper.dump( // message.getRoot(), connection.sender); // KJ_ DBG(msg); auto incomingMessage = kj::heap(messageToFlatArray(message)); auto connectionPtr = &connection; connection.tasks->add(kj::evalLater( [connectionPtr,message=kj::mv(incomingMessage)]() mutable { KJ_IF_MAYBE(p, connectionPtr->partner) { if (p->fulfillers.empty()) { p->messages.push(kj::mv(message)); } else { ++p->network.received; p->fulfillers.front()->fulfill( kj::Own(kj::mv(message))); p->fulfillers.pop(); } } })); } size_t sizeInWords() override { return message.sizeInWords(); } private: ConnectionImpl& connection; MallocMessageBuilder message; }; test::TestSturdyRefHostId::Reader getPeerVatId() override { // Not actually implemented for the purpose of this test. return test::TestSturdyRefHostId::Reader(); } kj::Own newOutgoingMessage(uint firstSegmentWordSize) override { return kj::heap(*this, firstSegmentWordSize); } kj::Promise>> receiveIncomingMessage() override { KJ_IF_MAYBE(e, networkException) { return kj::cp(*e); } if (messages.empty()) { KJ_IF_MAYBE(f, fulfillOnEnd) { f->get()->fulfill(); return kj::Maybe>(nullptr); } else { auto paf = kj::newPromiseAndFulfiller>>(); fulfillers.push(kj::mv(paf.fulfiller)); return kj::mv(paf.promise); } } else { ++network.received; auto result = kj::mv(messages.front()); messages.pop(); return kj::Maybe>(kj::mv(result)); } } kj::Promise shutdown() override { KJ_IF_MAYBE(e, network.shutdownExceptionToThrow) { return kj::cp(*e); } KJ_IF_MAYBE(p, partner) { auto paf = kj::newPromiseAndFulfiller(); p->fulfillOnEnd = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } else { return kj::READY_NOW; } } void taskFailed(kj::Exception&& exception) override { ADD_FAILURE() << kj::str(exception).cStr(); } private: TestNetworkAdapter& network; RpcDumper::Sender sender KJ_UNUSED_MEMBER; kj::Maybe partner; kj::Maybe networkException; std::queue>>>> fulfillers; std::queue> messages; kj::Maybe>> fulfillOnEnd; kj::Own tasks; }; kj::Maybe> connect(test::TestSturdyRefHostId::Reader hostId) override { if (hostId.getHost() == self) { return nullptr; } TestNetworkAdapter& dst = KJ_REQUIRE_NONNULL(network.find(hostId.getHost())); auto iter = connections.find(&dst); if (iter == connections.end()) { auto local = kj::refcounted(*this, RpcDumper::CLIENT); auto remote = kj::refcounted(dst, RpcDumper::SERVER); local->attach(*remote); connections[&dst] = kj::addRef(*local); dst.connections[this] = kj::addRef(*remote); if (dst.fulfillerQueue.empty()) { dst.connectionQueue.push(kj::mv(remote)); } else { dst.fulfillerQueue.front()->fulfill(kj::mv(remote)); dst.fulfillerQueue.pop(); } return kj::Own(kj::mv(local)); } else { return kj::Own(kj::addRef(*iter->second)); } } kj::Promise> accept() override { if (connectionQueue.empty()) { auto paf = kj::newPromiseAndFulfiller>(); fulfillerQueue.push(kj::mv(paf.fulfiller)); return kj::mv(paf.promise); } else { auto result = kj::mv(connectionQueue.front()); connectionQueue.pop(); return kj::mv(result); } } void setShutdownExceptionToThrow(kj::Exception&& e) { shutdownExceptionToThrow = kj::mv(e); } private: TestNetwork& network; kj::StringPtr self; uint sent = 0; uint received = 0; kj::Maybe shutdownExceptionToThrow = nullptr; std::map> connections; std::queue>>> fulfillerQueue; std::queue> connectionQueue; kj::Function sendCallback = [](MessageBuilder&) { return true; }; }; TestNetwork::~TestNetwork() noexcept(false) {} TestNetworkAdapter& TestNetwork::add(kj::StringPtr name) { return *(map[name] = kj::heap(*this, name)); } // ======================================================================================= class TestRestorer final: public SturdyRefRestorer { public: int callCount = 0; int handleCount = 0; Capability::Client restore(test::TestSturdyRefObjectId::Reader objectId) override { switch (objectId.getTag()) { case test::TestSturdyRefObjectId::Tag::TEST_INTERFACE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_EXTENDS: return Capability::Client(newBrokenCap("No TestExtends implemented.")); case test::TestSturdyRefObjectId::Tag::TEST_PIPELINE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLEE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLER: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF: return kj::heap(callCount, handleCount); } KJ_UNREACHABLE; } }; struct TestContext { kj::EventLoop loop; kj::WaitScope waitScope; TestNetwork network; TestRestorer restorer; TestNetworkAdapter& clientNetwork; TestNetworkAdapter& serverNetwork; RpcSystem rpcClient; RpcSystem rpcServer; TestContext() : waitScope(loop), clientNetwork(network.add("client")), serverNetwork(network.add("server")), rpcClient(makeRpcClient(clientNetwork)), rpcServer(makeRpcServer(serverNetwork, restorer)) {} TestContext(Capability::Client bootstrap) : waitScope(loop), clientNetwork(network.add("client")), serverNetwork(network.add("server")), rpcClient(makeRpcClient(clientNetwork)), rpcServer(makeRpcServer(serverNetwork, bootstrap)) {} Capability::Client connect(test::TestSturdyRefObjectId::Tag tag) { MallocMessageBuilder refMessage(128); auto ref = refMessage.initRoot(); auto hostId = ref.initHostId(); hostId.setHost("server"); ref.getObjectId().initAs().setTag(tag); return rpcClient.restore(hostId, ref.getObjectId()); } }; TEST(Rpc, Basic) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_INTERFACE) .castAs(); auto request1 = client.fooRequest(); request1.setI(123); request1.setJ(true); auto promise1 = request1.send(); // We used to call bar() after baz(), hence the numbering, but this masked the case where the // RPC system actually disconnected on bar() (thus returning an exception, which we decided // was expected). bool barFailed = false; auto request3 = client.barRequest(); auto promise3 = request3.send().then( [](Response&& response) { ADD_FAILURE() << "Expected bar() call to fail."; }, [&](kj::Exception&& e) { barFailed = true; }); auto request2 = client.bazRequest(); initTestMessage(request2.initS()); auto promise2 = request2.send(); EXPECT_EQ(0, context.restorer.callCount); auto response1 = promise1.wait(context.waitScope); EXPECT_EQ("foo", response1.getX()); auto response2 = promise2.wait(context.waitScope); promise3.wait(context.waitScope); EXPECT_EQ(2, context.restorer.callCount); EXPECT_TRUE(barFailed); } TEST(Rpc, Pipelining) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_PIPELINE) .castAs(); int chainedCallCount = 0; auto request = client.getCapRequest(); request.setN(234); request.setInCap(kj::heap(chainedCallCount)); auto promise = request.send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, context.restorer.callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(context.waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(context.waitScope); checkTestMessage(response2); EXPECT_EQ(3, context.restorer.callCount); EXPECT_EQ(1, chainedCallCount); } KJ_TEST("RPC sendForPipeline()") { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_PIPELINE) .castAs(); int chainedCallCount = 0; auto request = client.getCapRequest(); request.setN(234); request.setInCap(kj::heap(chainedCallCount)); auto pipeline = request.sendForPipeline(); auto pipelineRequest = pipeline.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = pipeline.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); pipeline = nullptr; // Just to be annoying, drop the original pipeline. EXPECT_EQ(0, context.restorer.callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(context.waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(context.waitScope); checkTestMessage(response2); EXPECT_EQ(3, context.restorer.callCount); EXPECT_EQ(1, chainedCallCount); } KJ_TEST("RPC context.setPipeline") { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_PIPELINE) .castAs(); auto promise = client.getCapPipelineOnlyRequest().send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); EXPECT_EQ(0, context.restorer.callCount); auto response = pipelinePromise.wait(context.waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(context.waitScope); checkTestMessage(response2); EXPECT_EQ(3, context.restorer.callCount); // The original promise never completed. KJ_EXPECT(!promise.poll(context.waitScope)); } TEST(Rpc, Release) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto handle1 = client.getHandleRequest().send().wait(context.waitScope).getHandle(); auto promise = client.getHandleRequest().send(); auto handle2 = promise.wait(context.waitScope).getHandle(); EXPECT_EQ(2, context.restorer.handleCount); handle1 = nullptr; for (uint i = 0; i < 16; i++) kj::evalLater([]() {}).wait(context.waitScope); EXPECT_EQ(1, context.restorer.handleCount); handle2 = nullptr; for (uint i = 0; i < 16; i++) kj::evalLater([]() {}).wait(context.waitScope); EXPECT_EQ(1, context.restorer.handleCount); promise = nullptr; for (uint i = 0; i < 16; i++) kj::evalLater([]() {}).wait(context.waitScope); EXPECT_EQ(0, context.restorer.handleCount); } TEST(Rpc, ReleaseOnCancel) { // At one time, there was a bug where if a Return contained capabilities, but the client had // canceled the request and already send a Finish (which presumably didn't reach the server before // the Return), then we'd leak those caps. Test for that. TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); client.whenResolved().wait(context.waitScope); { auto promise = client.getHandleRequest().send(); // If the server receives cancellation too early, it won't even return a capability in the // results, it will just return "canceled". We want to emulate the case where the return message // and the cancel (finish) message cross paths. It turns out that exactly two evalLater()s get // us there. // // TODO(cleanup): This is fragile, but I'm not sure how else to write it without a ton // of scaffolding. kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); } for (uint i = 0; i < 16; i++) kj::evalLater([]() {}).wait(context.waitScope); EXPECT_EQ(0, context.restorer.handleCount); } TEST(Rpc, TailCall) { TestContext context; auto caller = context.connect(test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLER) .castAs(); int calleeCallCount = 0; test::TestTailCallee::Client callee(kj::heap(calleeCallCount)); auto request = caller.fooRequest(); request.setI(456); request.setCallee(callee); auto promise = request.send(); auto dependentCall0 = promise.getC().getCallSequenceRequest().send(); auto response = promise.wait(context.waitScope); EXPECT_EQ(456, response.getI()); EXPECT_EQ("from TestTailCaller", response.getT()); auto dependentCall1 = promise.getC().getCallSequenceRequest().send(); EXPECT_EQ(0, dependentCall0.wait(context.waitScope).getN()); EXPECT_EQ(1, dependentCall1.wait(context.waitScope).getN()); // TODO(someday): We used to initiate dependentCall2 here before waiting on the first two calls, // and the ordering was still "correct". But this was apparently by accident. Calling getC() on // the final response returns a different capability from calling getC() on the promise. There // are no guarantees on the ordering of calls on the response capability vs. the earlier // promise. When ordering matters, applications should take the original promise capability and // keep using that. In theory the RPC system could create continuity here, but it would be // annoying: for each capability that had been fetched on the promise, it would need to // traverse to the same capability in the final response and swap it out in-place for the // pipelined cap returned earlier. Maybe we'll determine later that that's really needed but // for now I'm not gonna do it. auto dependentCall2 = response.getC().getCallSequenceRequest().send(); EXPECT_EQ(2, dependentCall2.wait(context.waitScope).getN()); EXPECT_EQ(1, calleeCallCount); EXPECT_EQ(1, context.restorer.callCount); } class TestHangingTailCallee final: public test::TestTailCallee::Server { public: TestHangingTailCallee(int& callCount, int& cancelCount) : callCount(callCount), cancelCount(cancelCount) {} kj::Promise foo(FooContext context) override { ++callCount; return kj::Promise(kj::NEVER_DONE) .attach(kj::defer([&cancelCount = cancelCount]() { ++cancelCount; })); } private: int& callCount; int& cancelCount; }; class TestRacingTailCaller final: public test::TestTailCaller::Server { public: TestRacingTailCaller(kj::Promise unblock): unblock(kj::mv(unblock)) {} kj::Promise foo(FooContext context) override { return unblock.then([context]() mutable { auto tailRequest = context.getParams().getCallee().fooRequest(); return context.tailCall(kj::mv(tailRequest)); }); } private: kj::Promise unblock; }; TEST(Rpc, TailCallCancel) { TestContext context; auto caller = context.connect(test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLER) .castAs(); int callCount = 0, cancelCount = 0; test::TestTailCallee::Client callee(kj::heap(callCount, cancelCount)); { auto request = caller.fooRequest(); request.setCallee(callee); auto promise = request.send(); KJ_ASSERT(callCount == 0); KJ_ASSERT(cancelCount == 0); KJ_ASSERT(!promise.poll(context.waitScope)); KJ_ASSERT(callCount == 1); KJ_ASSERT(cancelCount == 0); } kj::Promise(kj::NEVER_DONE).poll(context.waitScope); KJ_ASSERT(callCount == 1); KJ_ASSERT(cancelCount == 1); } TEST(Rpc, TailCallCancelRace) { auto paf = kj::newPromiseAndFulfiller(); TestContext context(kj::heap(kj::mv(paf.promise))); MallocMessageBuilder serverHostIdBuilder; auto serverHostId = serverHostIdBuilder.getRoot(); serverHostId.setHost("server"); auto caller = context.rpcClient.bootstrap(serverHostId).castAs(); int callCount = 0, cancelCount = 0; test::TestTailCallee::Client callee(kj::heap(callCount, cancelCount)); { auto request = caller.fooRequest(); request.setCallee(callee); auto promise = request.send(); KJ_ASSERT(callCount == 0); KJ_ASSERT(cancelCount == 0); KJ_ASSERT(!promise.poll(context.waitScope)); KJ_ASSERT(callCount == 0); KJ_ASSERT(cancelCount == 0); // Unblock the server and at the same time cancel the client. paf.fulfiller->fulfill(); } kj::Promise(kj::NEVER_DONE).poll(context.waitScope); KJ_ASSERT(callCount == 1); KJ_ASSERT(cancelCount == 1); } TEST(Rpc, Cancellation) { // Tests cancellation. TestContext context; auto paf = kj::newPromiseAndFulfiller(); bool destroyed = false; auto destructionPromise = paf.promise.then([&]() { destroyed = true; }).eagerlyEvaluate(nullptr); auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); kj::Promise promise = nullptr; bool returned = false; { auto request = client.expectCancelRequest(); request.setCap(kj::heap(kj::mv(paf.fulfiller))); promise = request.send().then( [&](Response&& response) { returned = true; }).eagerlyEvaluate(nullptr); } kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); // We can detect that the method was canceled because it will drop the cap. EXPECT_FALSE(destroyed); EXPECT_FALSE(returned); promise = nullptr; // request cancellation destructionPromise.wait(context.waitScope); EXPECT_TRUE(destroyed); EXPECT_FALSE(returned); } TEST(Rpc, PromiseResolve) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); int chainedCallCount = 0; auto request = client.callFooRequest(); auto request2 = client.callFooWhenResolvedRequest(); auto paf = kj::newPromiseAndFulfiller(); { auto fork = paf.promise.fork(); request.setCap(fork.addBranch()); request2.setCap(fork.addBranch()); } auto promise = request.send(); auto promise2 = request2.send(); // Make sure getCap() has been called on the server side by sending another call and waiting // for it. EXPECT_EQ(2, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); EXPECT_EQ(3, context.restorer.callCount); // OK, now fulfill the local promise. paf.fulfiller->fulfill(kj::heap(chainedCallCount)); // We should now be able to wait for getCap() to finish. EXPECT_EQ("bar", promise.wait(context.waitScope).getS()); EXPECT_EQ("bar", promise2.wait(context.waitScope).getS()); EXPECT_EQ(3, context.restorer.callCount); EXPECT_EQ(2, chainedCallCount); } TEST(Rpc, RetainAndRelease) { TestContext context; auto paf = kj::newPromiseAndFulfiller(); bool destroyed = false; auto destructionPromise = paf.promise.then([&]() { destroyed = true; }).eagerlyEvaluate(nullptr); { auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); { auto request = client.holdRequest(); request.setCap(kj::heap(kj::mv(paf.fulfiller))); request.send().wait(context.waitScope); } // Do some other call to add a round trip. EXPECT_EQ(1, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); // Shouldn't be destroyed because it's being held by the server. EXPECT_FALSE(destroyed); // We can ask it to call the held capability. EXPECT_EQ("bar", client.callHeldRequest().send().wait(context.waitScope).getS()); { // We can get the cap back from it. auto capCopy = client.getHeldRequest().send().wait(context.waitScope).getCap(); { // And call it, without any network communications. uint oldSentCount = context.clientNetwork.getSentCount(); auto request = capCopy.fooRequest(); request.setI(123); request.setJ(true); EXPECT_EQ("foo", request.send().wait(context.waitScope).getX()); EXPECT_EQ(oldSentCount, context.clientNetwork.getSentCount()); } { // We can send another copy of the same cap to another method, and it works. auto request = client.callFooRequest(); request.setCap(capCopy); EXPECT_EQ("bar", request.send().wait(context.waitScope).getS()); } } // Give some time to settle. EXPECT_EQ(5, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); EXPECT_EQ(6, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); EXPECT_EQ(7, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); // Can't be destroyed, we haven't released it. EXPECT_FALSE(destroyed); } // We released our client, which should cause the server to be released, which in turn will // release the cap pointing back to us. destructionPromise.wait(context.waitScope); EXPECT_TRUE(destroyed); } TEST(Rpc, Cancel) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto paf = kj::newPromiseAndFulfiller(); bool destroyed = false; auto destructionPromise = paf.promise.then([&]() { destroyed = true; }).eagerlyEvaluate(nullptr); { auto request = client.neverReturnRequest(); request.setCap(kj::heap(kj::mv(paf.fulfiller))); { auto responsePromise = request.send(); // Allow some time to settle. EXPECT_EQ(1, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); EXPECT_EQ(2, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); // The cap shouldn't have been destroyed yet because the call never returned. EXPECT_FALSE(destroyed); } } // Now the cap should be released. destructionPromise.wait(context.waitScope); EXPECT_TRUE(destroyed); } TEST(Rpc, SendTwice) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto paf = kj::newPromiseAndFulfiller(); bool destroyed = false; auto destructionPromise = paf.promise.then([&]() { destroyed = true; }).eagerlyEvaluate(nullptr); auto cap = test::TestInterface::Client(kj::heap(kj::mv(paf.fulfiller))); { auto request = client.callFooRequest(); request.setCap(cap); EXPECT_EQ("bar", request.send().wait(context.waitScope).getS()); } // Allow some time for the server to release `cap`. EXPECT_EQ(1, client.getCallSequenceRequest().send().wait(context.waitScope).getN()); { // More requests with the same cap. auto request = client.callFooRequest(); auto request2 = client.callFooRequest(); request.setCap(cap); request2.setCap(kj::mv(cap)); auto promise = request.send(); auto promise2 = request2.send(); EXPECT_EQ("bar", promise.wait(context.waitScope).getS()); EXPECT_EQ("bar", promise2.wait(context.waitScope).getS()); } // Now the cap should be released. destructionPromise.wait(context.waitScope); EXPECT_TRUE(destroyed); } RemotePromise getCallSequence( test::TestCallOrder::Client& client, uint expected) { auto req = client.getCallSequenceRequest(); req.setExpected(expected); return req.send(); } TEST(Rpc, Embargo) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto cap = test::TestCallOrder::Client(kj::heap()); auto earlyCall = client.getCallSequenceRequest().send(); auto echoRequest = client.echoRequest(); echoRequest.setCap(cap); auto echo = echoRequest.send(); auto pipeline = echo.getCap(); auto call0 = getCallSequence(pipeline, 0); auto call1 = getCallSequence(pipeline, 1); earlyCall.wait(context.waitScope); auto call2 = getCallSequence(pipeline, 2); auto resolved = echo.wait(context.waitScope).getCap(); auto call3 = getCallSequence(pipeline, 3); auto call4 = getCallSequence(pipeline, 4); auto call5 = getCallSequence(pipeline, 5); EXPECT_EQ(0, call0.wait(context.waitScope).getN()); EXPECT_EQ(1, call1.wait(context.waitScope).getN()); EXPECT_EQ(2, call2.wait(context.waitScope).getN()); EXPECT_EQ(3, call3.wait(context.waitScope).getN()); EXPECT_EQ(4, call4.wait(context.waitScope).getN()); EXPECT_EQ(5, call5.wait(context.waitScope).getN()); } TEST(Rpc, EmbargoUnwrap) { // Test that embargos properly block unwraping a capability using CapabilityServerSet. TestContext context; capnp::CapabilityServerSet capSet; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto cap = capSet.add(kj::heap()); auto earlyCall = client.getCallSequenceRequest().send(); auto echoRequest = client.echoRequest(); echoRequest.setCap(cap); auto echo = echoRequest.send(); auto pipeline = echo.getCap(); auto unwrap = capSet.getLocalServer(pipeline) .then([](kj::Maybe unwrapped) { return kj::downcast(KJ_ASSERT_NONNULL(unwrapped)).getCount(); }).eagerlyEvaluate(nullptr); auto call0 = getCallSequence(pipeline, 0); auto call1 = getCallSequence(pipeline, 1); earlyCall.wait(context.waitScope); auto call2 = getCallSequence(pipeline, 2); auto resolved = echo.wait(context.waitScope).getCap(); auto call3 = getCallSequence(pipeline, 4); auto call4 = getCallSequence(pipeline, 4); auto call5 = getCallSequence(pipeline, 5); EXPECT_EQ(0, call0.wait(context.waitScope).getN()); EXPECT_EQ(1, call1.wait(context.waitScope).getN()); EXPECT_EQ(2, call2.wait(context.waitScope).getN()); EXPECT_EQ(3, call3.wait(context.waitScope).getN()); EXPECT_EQ(4, call4.wait(context.waitScope).getN()); EXPECT_EQ(5, call5.wait(context.waitScope).getN()); uint unwrappedAt = unwrap.wait(context.waitScope); KJ_EXPECT(unwrappedAt >= 3, unwrappedAt); } template void expectPromiseThrows(kj::Promise&& promise, kj::WaitScope& waitScope) { EXPECT_TRUE(promise.then([](T&&) { return false; }, [](kj::Exception&&) { return true; }) .wait(waitScope)); } template <> void expectPromiseThrows(kj::Promise&& promise, kj::WaitScope& waitScope) { EXPECT_TRUE(promise.then([]() { return false; }, [](kj::Exception&&) { return true; }) .wait(waitScope)); } TEST(Rpc, EmbargoError) { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto paf = kj::newPromiseAndFulfiller(); auto cap = test::TestCallOrder::Client(kj::mv(paf.promise)); auto earlyCall = client.getCallSequenceRequest().send(); auto echoRequest = client.echoRequest(); echoRequest.setCap(cap); auto echo = echoRequest.send(); auto pipeline = echo.getCap(); auto call0 = getCallSequence(pipeline, 0); auto call1 = getCallSequence(pipeline, 1); earlyCall.wait(context.waitScope); auto call2 = getCallSequence(pipeline, 2); auto resolved = echo.wait(context.waitScope).getCap(); auto call3 = getCallSequence(pipeline, 3); auto call4 = getCallSequence(pipeline, 4); auto call5 = getCallSequence(pipeline, 5); paf.fulfiller->rejectIfThrows([]() { KJ_FAIL_ASSERT("foo") { break; } }); expectPromiseThrows(kj::mv(call0), context.waitScope); expectPromiseThrows(kj::mv(call1), context.waitScope); expectPromiseThrows(kj::mv(call2), context.waitScope); expectPromiseThrows(kj::mv(call3), context.waitScope); expectPromiseThrows(kj::mv(call4), context.waitScope); expectPromiseThrows(kj::mv(call5), context.waitScope); // Verify that we're still connected (there were no protocol errors). getCallSequence(client, 1).wait(context.waitScope); } TEST(Rpc, EmbargoNull) { // Set up a situation where we pipeline on a capability that ends up coming back null. This // should NOT cause a Disembargo to be sent, but due to a bug in earlier versions of Cap'n Proto, // a Disembargo was indeed sent to the null capability, which caused the server to disconnect // due to protocol error. TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto promise = client.getNullRequest().send(); auto cap = promise.getNullCap(); auto call0 = cap.getCallSequenceRequest().send(); promise.wait(context.waitScope); auto call1 = cap.getCallSequenceRequest().send(); expectPromiseThrows(kj::mv(call0), context.waitScope); expectPromiseThrows(kj::mv(call1), context.waitScope); // Verify that we're still connected (there were no protocol errors). getCallSequence(client, 0).wait(context.waitScope); } TEST(Rpc, CallBrokenPromise) { // Tell the server to call back to a promise client, then resolve the promise to an error. TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto paf = kj::newPromiseAndFulfiller(); { auto req = client.holdRequest(); req.setCap(kj::mv(paf.promise)); req.send().wait(context.waitScope); } bool returned = false; auto req = client.callHeldRequest().send() .then([&](capnp::Response&&) { returned = true; }, [&](kj::Exception&& e) { returned = true; kj::throwRecoverableException(kj::mv(e)); }).eagerlyEvaluate(nullptr); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); EXPECT_FALSE(returned); paf.fulfiller->rejectIfThrows([]() { KJ_FAIL_ASSERT("foo") { break; } }); expectPromiseThrows(kj::mv(req), context.waitScope); EXPECT_TRUE(returned); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); kj::evalLater([]() {}).wait(context.waitScope); // Verify that we're still connected (there were no protocol errors). getCallSequence(client, 1).wait(context.waitScope); } TEST(Rpc, Abort) { // Verify that aborts are received. TestContext context; MallocMessageBuilder refMessage(128); auto hostId = refMessage.initRoot(); hostId.setHost("server"); auto conn = KJ_ASSERT_NONNULL(context.clientNetwork.connect(hostId)); { // Send an invalid message (Return to non-existent question). auto msg = conn->newOutgoingMessage(128); auto body = msg->getBody().initAs().initReturn(); body.setAnswerId(1234); body.setCanceled(); msg->send(); } auto reply = KJ_ASSERT_NONNULL(conn->receiveIncomingMessage().wait(context.waitScope)); EXPECT_EQ(rpc::Message::ABORT, reply->getBody().getAs().which()); EXPECT_TRUE(conn->receiveIncomingMessage().wait(context.waitScope) == nullptr); } KJ_TEST("handles exceptions thrown during disconnect") { // This is similar to the earlier "abort" test, but throws an exception on // connection shutdown, to exercise the RpcConnectionState error handler. TestContext context; MallocMessageBuilder refMessage(128); auto hostId = refMessage.initRoot(); hostId.setHost("server"); context.serverNetwork.setShutdownExceptionToThrow( KJ_EXCEPTION(FAILED, "a_disconnect_exception")); auto conn = KJ_ASSERT_NONNULL(context.clientNetwork.connect(hostId)); { // Send an invalid message (Return to non-existent question). auto msg = conn->newOutgoingMessage(128); auto body = msg->getBody().initAs().initReturn(); body.setAnswerId(1234); body.setCanceled(); msg->send(); } { // The internal exception handler of RpcSystemBase logs exceptions thrown // during disconnect, which the test framework will flag as a failure if we // don't explicitly tell it to expect the logged output. KJ_EXPECT_LOG(ERROR, "a_disconnect_exception"); // Force outstanding promises to completion. The server should detect the // invalid message and disconnect, which should cause the connection's // disconnect() to throw an exception that will then be handled by a // RpcConnectionState handler. Since other state instances were freed prior // to the handler invocation, this caused failures in earlier versions of // the code when run under asan. kj::Promise(kj::NEVER_DONE).poll(context.waitScope); } } KJ_TEST("loopback bootstrap()") { int callCount = 0; test::TestInterface::Client bootstrap = kj::heap(callCount); MallocMessageBuilder hostIdBuilder; auto hostId = hostIdBuilder.getRoot(); hostId.setHost("server"); TestContext context(bootstrap); auto client = context.rpcServer.bootstrap(hostId).castAs(); auto request = client.fooRequest(); request.setI(123); request.setJ(true); auto response = request.send().wait(context.waitScope); KJ_EXPECT(response.getX() == "foo"); KJ_EXPECT(callCount == 1); } KJ_TEST("method throws exception") { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); kj::Maybe maybeException; client.throwExceptionRequest().send().ignoreResult() .catch_([&](kj::Exception&& e) { maybeException = kj::mv(e); }).wait(context.waitScope); auto exception = KJ_ASSERT_NONNULL(maybeException); KJ_EXPECT(exception.getDescription() == "remote exception: test exception"); KJ_EXPECT(exception.getRemoteTrace() == nullptr); } KJ_TEST("method throws exception won't redundantly add remote exception prefix") { TestContext context; auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); kj::Maybe maybeException; client.throwRemoteExceptionRequest().send().ignoreResult() .catch_([&](kj::Exception&& e) { maybeException = kj::mv(e); }).wait(context.waitScope); auto exception = KJ_ASSERT_NONNULL(maybeException); KJ_EXPECT(exception.getDescription() == "remote exception: test exception"); KJ_EXPECT(exception.getRemoteTrace() == nullptr); } KJ_TEST("method throws exception with trace encoder") { TestContext context; context.rpcServer.setTraceEncoder([](const kj::Exception& e) { return kj::str("trace for ", e.getDescription()); }); auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); kj::Maybe maybeException; client.throwExceptionRequest().send().ignoreResult() .catch_([&](kj::Exception&& e) { maybeException = kj::mv(e); }).wait(context.waitScope); auto exception = KJ_ASSERT_NONNULL(maybeException); KJ_EXPECT(exception.getDescription() == "remote exception: test exception"); KJ_EXPECT(exception.getRemoteTrace() == "trace for test exception"); } KJ_TEST("when OutgoingRpcMessage::send() throws, we don't leak exports") { // When OutgoingRpcMessage::send() throws an exception on a Call message, we need to clean up // anything that had been added to the export table as part of the call. At one point this // cleanup was missing, so exports would leak. TestContext context; uint32_t expectedExportNumber = 0; uint interceptCount = 0; bool shouldThrowFromSend = false; context.clientNetwork.onSend([&](MessageBuilder& builder) { auto message = builder.getRoot().asReader(); if (message.isCall()) { auto call = message.getCall(); if (call.getInterfaceId() == capnp::typeId() && call.getMethodId() == 0) { // callFoo() request, expect a capability in the param caps. Specifically we expect a // promise, because that's what we send below. auto capTable = call.getParams().getCapTable(); KJ_ASSERT(capTable.size() == 1); auto desc = capTable[0]; KJ_ASSERT(desc.isSenderPromise()); KJ_ASSERT(desc.getSenderPromise() == expectedExportNumber); ++interceptCount; if (shouldThrowFromSend) { kj::throwRecoverableException(KJ_EXCEPTION(FAILED, "intercepted")); return false; // only matters when -fno-exceptions } } } return true; }); auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); { shouldThrowFromSend = true; auto req = client.callFooRequest(); req.setCap(kj::Promise(kj::NEVER_DONE)); req.send().then([](auto&&) { KJ_FAIL_ASSERT("should have thrown"); }, [](kj::Exception&& e) { KJ_EXPECT(e.getDescription() == "intercepted", e); }).wait(context.waitScope); } KJ_EXPECT(interceptCount == 1); // Sending again should use the same export number, because the export table entry should have // been released when send() threw. (At one point, this was a bug...) { shouldThrowFromSend = true; auto req = client.callFooRequest(); req.setCap(kj::Promise(kj::NEVER_DONE)); req.send().then([](auto&&) { KJ_FAIL_ASSERT("should have thrown"); }, [](kj::Exception&& e) { KJ_EXPECT(e.getDescription() == "intercepted", e); }).wait(context.waitScope); } KJ_EXPECT(interceptCount == 2); // Now lets start a call that doesn't throw. The export number should still be zero because // the previous exports were released. { shouldThrowFromSend = false; auto req = client.callFooRequest(); req.setCap(kj::Promise(kj::NEVER_DONE)); auto promise = req.send(); KJ_EXPECT(!promise.poll(context.waitScope)); KJ_EXPECT(interceptCount == 3); } // We canceled the previous call, BUT the exported capability is still present until the other // side drops it, which it won't because the call isn't marked cancelable and never completes. // Now, let's send another call. This time, we expect a new export number will actually be // allocated. { shouldThrowFromSend = false; expectedExportNumber = 1; auto req = client.callFooRequest(); auto paf = kj::newPromiseAndFulfiller(); req.setCap(kj::mv(paf.promise)); auto promise = req.send(); KJ_EXPECT(!promise.poll(context.waitScope)); KJ_EXPECT(interceptCount == 4); // Now let's actually let the RPC complete so we can verify the RPC system isn't broken or // anything. int callCount = 0; paf.fulfiller->fulfill(kj::heap(callCount)); auto resp = promise.wait(context.waitScope); KJ_EXPECT(resp.getS() == "bar"); KJ_EXPECT(callCount == 1); } // Now if we do yet another call, it'll reuse export number 1. { shouldThrowFromSend = false; expectedExportNumber = 1; auto req = client.callFooRequest(); req.setCap(kj::Promise(kj::NEVER_DONE)); auto promise = req.send(); KJ_EXPECT(!promise.poll(context.waitScope)); KJ_EXPECT(interceptCount == 5); } } KJ_TEST("export the same promise twice") { TestContext context; bool exportIsPromise; uint32_t expectedExportNumber; uint interceptCount = 0; context.clientNetwork.onSend([&](MessageBuilder& builder) { auto message = builder.getRoot().asReader(); if (message.isCall()) { auto call = message.getCall(); if (call.getInterfaceId() == capnp::typeId() && call.getMethodId() == 0) { // callFoo() request, expect a capability in the param caps. Specifically we expect a // promise, because that's what we send below. auto capTable = call.getParams().getCapTable(); KJ_ASSERT(capTable.size() == 1); auto desc = capTable[0]; if (exportIsPromise) { KJ_ASSERT(desc.isSenderPromise()); KJ_ASSERT(desc.getSenderPromise() == expectedExportNumber); } else { KJ_ASSERT(desc.isSenderHosted()); KJ_ASSERT(desc.getSenderHosted() == expectedExportNumber); } ++interceptCount; } } return true; }); auto client = context.connect(test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF) .castAs(); auto sendReq = [&](test::TestInterface::Client cap) { auto req = client.callFooRequest(); req.setCap(kj::mv(cap)); return req.send(); }; auto expectNeverDone = [&](auto& promise) { if (promise.poll(context.waitScope)) { promise.wait(context.waitScope); // let it throw if it's going to KJ_FAIL_ASSERT("promise finished without throwing"); } }; int callCount = 0; test::TestInterface::Client normalCap = kj::heap(callCount); test::TestInterface::Client promiseCap = kj::Promise(kj::NEVER_DONE); // Send request with a promise capability in the params. exportIsPromise = true; expectedExportNumber = 0; auto promise1 = sendReq(promiseCap); expectNeverDone(promise1); KJ_EXPECT(interceptCount == 1); // Send a second request with the same promise should use the same export table entry. auto promise2 = sendReq(promiseCap); expectNeverDone(promise2); KJ_EXPECT(interceptCount == 2); // Sending a request with a different promise should use a different export table entry. expectedExportNumber = 1; auto promise3 = sendReq(kj::Promise(kj::NEVER_DONE)); expectNeverDone(promise3); KJ_EXPECT(interceptCount == 3); // Now try sending a non-promise cap. We'll send all these requests at once before waiting on // any of them since these will actually complete. exportIsPromise = false; expectedExportNumber = 2; auto promise4 = sendReq(normalCap); auto promise5 = sendReq(normalCap); expectedExportNumber = 3; auto promise6 = sendReq(kj::heap(callCount)); KJ_EXPECT(interceptCount == 6); KJ_EXPECT(promise4.wait(context.waitScope).getS() == "bar"); KJ_EXPECT(promise5.wait(context.waitScope).getS() == "bar"); KJ_EXPECT(promise6.wait(context.waitScope).getS() == "bar"); KJ_EXPECT(callCount == 3); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize-async.c++0000644000175000017500000010221014712011043022213 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // Includes just for need SOL_SOCKET and SO_SNDBUF #if _WIN32 #include #include #include #include #else #include #endif #include "serialize-async.h" #include "serialize.h" #include #include namespace capnp { namespace { class AsyncMessageReader: public MessageReader { public: inline AsyncMessageReader(ReaderOptions options): MessageReader(options) { memset(firstWord, 0, sizeof(firstWord)); } ~AsyncMessageReader() noexcept(false) {} kj::Promise read(kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace); kj::Promise> readWithFds( kj::AsyncCapabilityStream& inputStream, kj::ArrayPtr fds, kj::ArrayPtr scratchSpace); // implements MessageReader ---------------------------------------- kj::ArrayPtr getSegment(uint id) override { if (id >= segmentCount()) { return nullptr; } else { uint32_t size = id == 0 ? segment0Size() : moreSizes[id - 1].get(); return kj::arrayPtr(segmentStarts[id], size); } } private: _::WireValue firstWord[2]; kj::Array<_::WireValue> moreSizes; kj::Array segmentStarts; kj::Array ownedSpace; // Only if scratchSpace wasn't big enough. inline uint segmentCount() { return firstWord[0].get() + 1; } inline uint segment0Size() { return firstWord[1].get(); } kj::Promise readAfterFirstWord( kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace); kj::Promise readSegments( kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace); }; kj::Promise AsyncMessageReader::read(kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace) { return inputStream.tryRead(firstWord, sizeof(firstWord), sizeof(firstWord)) .then([this,&inputStream,KJ_CPCAP(scratchSpace)](size_t n) mutable -> kj::Promise { if (n == 0) { return false; } else if (n < sizeof(firstWord)) { // EOF in first word. kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); return false; } return readAfterFirstWord(inputStream, scratchSpace).then([]() { return true; }); }); } kj::Promise> AsyncMessageReader::readWithFds( kj::AsyncCapabilityStream& inputStream, kj::ArrayPtr fds, kj::ArrayPtr scratchSpace) { return inputStream.tryReadWithFds(firstWord, sizeof(firstWord), sizeof(firstWord), fds.begin(), fds.size()) .then([this,&inputStream,KJ_CPCAP(scratchSpace)] (kj::AsyncCapabilityStream::ReadResult result) mutable -> kj::Promise> { if (result.byteCount == 0) { return kj::Maybe(nullptr); } else if (result.byteCount < sizeof(firstWord)) { // EOF in first word. kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); return kj::Maybe(nullptr); } return readAfterFirstWord(inputStream, scratchSpace) .then([result]() -> kj::Maybe { return result.capCount; }); }); } kj::Promise AsyncMessageReader::readAfterFirstWord(kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace) { if (segmentCount() == 0) { firstWord[1].set(0); } // Reject messages with too many segments for security reasons. KJ_REQUIRE(segmentCount() < 512, "Message has too many segments.") { return kj::READY_NOW; // exception will be propagated } if (segmentCount() > 1) { // Read sizes for all segments except the first. Include padding if necessary. moreSizes = kj::heapArray<_::WireValue>(segmentCount() & ~1); return inputStream.read(moreSizes.begin(), moreSizes.size() * sizeof(moreSizes[0])) .then([this,&inputStream,KJ_CPCAP(scratchSpace)]() mutable { return readSegments(inputStream, scratchSpace); }); } else { return readSegments(inputStream, scratchSpace); } } kj::Promise AsyncMessageReader::readSegments(kj::AsyncInputStream& inputStream, kj::ArrayPtr scratchSpace) { size_t totalWords = segment0Size(); if (segmentCount() > 1) { for (uint i = 0; i < segmentCount() - 1; i++) { totalWords += moreSizes[i].get(); } } // Don't accept a message which the receiver couldn't possibly traverse without hitting the // traversal limit. Without this check, a malicious client could transmit a very large segment // size to make the receiver allocate excessive space and possibly crash. KJ_REQUIRE(totalWords <= getOptions().traversalLimitInWords, "Message is too large. To increase the limit on the receiving end, see " "capnp::ReaderOptions.") { return kj::READY_NOW; // exception will be propagated } if (scratchSpace.size() < totalWords) { // TODO(perf): Consider allocating each segment as a separate chunk to reduce memory // fragmentation. ownedSpace = kj::heapArray(totalWords); scratchSpace = ownedSpace; } segmentStarts = kj::heapArray(segmentCount()); segmentStarts[0] = scratchSpace.begin(); if (segmentCount() > 1) { size_t offset = segment0Size(); for (uint i = 1; i < segmentCount(); i++) { segmentStarts[i] = scratchSpace.begin() + offset; offset += moreSizes[i-1].get(); } } return inputStream.read(scratchSpace.begin(), totalWords * sizeof(word)); } } // namespace kj::Promise> readMessage( kj::AsyncInputStream& input, ReaderOptions options, kj::ArrayPtr scratchSpace) { auto reader = kj::heap(options); auto promise = reader->read(input, scratchSpace); return promise.then([reader = kj::mv(reader)](bool success) mutable -> kj::Own { if (!success) { kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); } return kj::mv(reader); }); } kj::Promise>> tryReadMessage( kj::AsyncInputStream& input, ReaderOptions options, kj::ArrayPtr scratchSpace) { auto reader = kj::heap(options); auto promise = reader->read(input, scratchSpace); return promise.then([reader = kj::mv(reader)](bool success) mutable -> kj::Maybe> { if (success) { return kj::mv(reader); } else { return nullptr; } }); } kj::Promise readMessage( kj::AsyncCapabilityStream& input, kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { auto reader = kj::heap(options); auto promise = reader->readWithFds(input, fdSpace, scratchSpace); return promise.then([reader = kj::mv(reader), fdSpace](kj::Maybe nfds) mutable -> MessageReaderAndFds { KJ_IF_MAYBE(n, nfds) { return { kj::mv(reader), fdSpace.slice(0, *n) }; } else { kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); return { kj::mv(reader), nullptr }; } }); } kj::Promise> tryReadMessage( kj::AsyncCapabilityStream& input, kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { auto reader = kj::heap(options); auto promise = reader->readWithFds(input, fdSpace, scratchSpace); return promise.then([reader = kj::mv(reader), fdSpace](kj::Maybe nfds) mutable -> kj::Maybe { KJ_IF_MAYBE(n, nfds) { return MessageReaderAndFds { kj::mv(reader), fdSpace.slice(0, *n) }; } else { return nullptr; } }); } // ======================================================================================= namespace { struct WriteArrays { // Holds arrays that must remain valid until a write completes. kj::Array<_::WireValue> table; kj::Array> pieces; }; inline size_t tableSizeForSegments(size_t segmentsSize) { return (segmentsSize + 2) & ~size_t(1); } // Helper function that allocates and fills the pointed-to table with info about the segments and // populates the pieces array with pointers to the segments. void fillWriteArraysWithMessage(kj::ArrayPtr> segments, kj::ArrayPtr<_::WireValue> table, kj::ArrayPtr> pieces) { KJ_REQUIRE(segments.size() > 0, "Tried to serialize uninitialized message."); // We write the segment count - 1 because this makes the first word zero for single-segment // messages, improving compression. We don't bother doing this with segment sizes because // one-word segments are rare anyway. table[0].set(segments.size() - 1); for (uint i = 0; i < segments.size(); i++) { table[i + 1].set(segments[i].size()); } if (segments.size() % 2 == 0) { // Set padding byte. table[segments.size() + 1].set(0); } KJ_ASSERT(pieces.size() == segments.size() + 1, "incorrectly sized pieces array during write"); pieces[0] = table.asBytes(); for (uint i = 0; i < segments.size(); i++) { pieces[i + 1] = segments[i].asBytes(); } } template kj::Promise writeMessageImpl(kj::ArrayPtr> segments, WriteFunc&& writeFunc) { KJ_REQUIRE(segments.size() > 0, "Tried to serialize uninitialized message."); WriteArrays arrays; arrays.table = kj::heapArray<_::WireValue>(tableSizeForSegments(segments.size())); arrays.pieces = kj::heapArray>(segments.size() + 1); fillWriteArraysWithMessage(segments, arrays.table, arrays.pieces); auto promise = writeFunc(arrays.pieces); // Make sure the arrays aren't freed until the write completes. return promise.then([arrays=kj::mv(arrays)]() {}); } template kj::Promise writeMessagesImpl( kj::ArrayPtr>> messages, WriteFunc&& writeFunc) { KJ_REQUIRE(messages.size() > 0, "Tried to serialize zero messages."); // Determine how large the shared table and pieces arrays needs to be. size_t tableSize = 0; size_t piecesSize = 0; for (auto& segments : messages) { tableSize += tableSizeForSegments(segments.size()); piecesSize += segments.size() + 1; } auto table = kj::heapArray<_::WireValue>(tableSize); auto pieces = kj::heapArray>(piecesSize); size_t tableValsWritten = 0; size_t piecesWritten = 0; for (auto i : kj::indices(messages)) { const size_t tableValsToWrite = tableSizeForSegments(messages[i].size()); const size_t piecesToWrite = messages[i].size() + 1; fillWriteArraysWithMessage( messages[i], table.slice(tableValsWritten, tableValsWritten + tableValsToWrite), pieces.slice(piecesWritten, piecesWritten + piecesToWrite)); tableValsWritten += tableValsToWrite; piecesWritten += piecesToWrite; } auto promise = writeFunc(pieces); return promise.attach(kj::mv(table), kj::mv(pieces)); } } // namespace kj::Promise writeMessage(kj::AsyncOutputStream& output, kj::ArrayPtr> segments) { return writeMessageImpl(segments, [&](kj::ArrayPtr> pieces) { return output.write(pieces); }); } kj::Promise writeMessage(kj::AsyncCapabilityStream& output, kj::ArrayPtr fds, kj::ArrayPtr> segments) { return writeMessageImpl(segments, [&](kj::ArrayPtr> pieces) { return output.writeWithFds(pieces[0], pieces.slice(1, pieces.size()), fds); }); } kj::Promise writeMessages( kj::AsyncOutputStream& output, kj::ArrayPtr>> messages) { return writeMessagesImpl(messages, [&](kj::ArrayPtr> pieces) { return output.write(pieces); }); } kj::Promise writeMessages( kj::AsyncOutputStream& output, kj::ArrayPtr builders) { auto messages = kj::heapArray>>(builders.size()); for (auto i : kj::indices(builders)) { messages[i] = builders[i]->getSegmentsForOutput(); } return writeMessages(output, messages); } kj::Promise MessageStream::writeMessages(kj::ArrayPtr messages) { if (messages.size() == 0) return kj::READY_NOW; kj::ArrayPtr remainingMessages; auto writeProm = [&]() { if (messages[0].fds.size() > 0) { // We have a message with FDs attached. We need to write any bare messages we've accumulated, // if any, then write the message with FDs, then continue on with any remaining messages. if (messages.size() > 1) { remainingMessages = messages.slice(1, messages.size()); } return writeMessage(messages[0].fds, messages[0].segments); } else { kj::Vector>> bareMessages(messages.size()); for(auto i : kj::zeroTo(messages.size())) { if (messages[i].fds.size() > 0) { break; } bareMessages.add(messages[i].segments); } if (messages.size() > bareMessages.size()) { remainingMessages = messages.slice(bareMessages.size(), messages.size()); } return writeMessages(bareMessages.asPtr()).attach(kj::mv(bareMessages)); } }(); if (remainingMessages.size() > 0) { return writeProm.then([this, remainingMessages]() mutable { return writeMessages(remainingMessages); }); } else { return writeProm; } } kj::Promise MessageStream::writeMessages(kj::ArrayPtr builders) { auto messages = kj::heapArray>>(builders.size()); for (auto i : kj::indices(builders)) { messages[i] = builders[i]->getSegmentsForOutput(); } return writeMessages(messages); } AsyncIoMessageStream::AsyncIoMessageStream(kj::AsyncIoStream& stream) : stream(stream) {}; kj::Promise> AsyncIoMessageStream::tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { return capnp::tryReadMessage(stream, options, scratchSpace) .then([](kj::Maybe> maybeReader) -> kj::Maybe { KJ_IF_MAYBE(reader, maybeReader) { return MessageReaderAndFds { kj::mv(*reader), nullptr }; } else { return nullptr; } }); } kj::Promise AsyncIoMessageStream::writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) { return capnp::writeMessage(stream, segments); } kj::Promise AsyncIoMessageStream::writeMessages( kj::ArrayPtr>> messages) { return capnp::writeMessages(stream, messages); } kj::Maybe getSendBufferSize(kj::AsyncIoStream& stream) { // TODO(perf): It might be nice to have a tryGetsockopt() that doesn't require catching // exceptions? int bufSize = 0; KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { uint len = sizeof(int); stream.getsockopt(SOL_SOCKET, SO_SNDBUF, &bufSize, &len); KJ_ASSERT(len == sizeof(bufSize)) { break; } })) { if (exception->getType() != kj::Exception::Type::UNIMPLEMENTED) { // TODO(someday): Figure out why getting SO_SNDBUF sometimes throws EINVAL. I suspect it // happens when the remote side has closed their read end, meaning we no longer have // a send buffer, but I don't know what is the best way to verify that that was actually // the reason. I'd prefer not to ignore EINVAL errors in general. // kj::throwRecoverableException(kj::mv(*exception)); } return nullptr; } return bufSize; } kj::Promise AsyncIoMessageStream::end() { stream.shutdownWrite(); return kj::READY_NOW; } kj::Maybe AsyncIoMessageStream::getSendBufferSize() { return capnp::getSendBufferSize(stream); } AsyncCapabilityMessageStream::AsyncCapabilityMessageStream(kj::AsyncCapabilityStream& stream) : stream(stream) {}; kj::Promise> AsyncCapabilityMessageStream::tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { return capnp::tryReadMessage(stream, fdSpace, options, scratchSpace); } kj::Promise AsyncCapabilityMessageStream::writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) { return capnp::writeMessage(stream, fds, segments); } kj::Promise AsyncCapabilityMessageStream::writeMessages( kj::ArrayPtr>> messages) { return capnp::writeMessages(stream, messages); } kj::Maybe AsyncCapabilityMessageStream::getSendBufferSize() { return capnp::getSendBufferSize(stream); } kj::Promise AsyncCapabilityMessageStream::end() { stream.shutdownWrite(); return kj::READY_NOW; } kj::Promise> MessageStream::readMessage( ReaderOptions options, kj::ArrayPtr scratchSpace) { return tryReadMessage(options, scratchSpace).then([](kj::Maybe> maybeResult) { KJ_IF_MAYBE(result, maybeResult) { return kj::mv(*result); } else { kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); KJ_UNREACHABLE; } }); } kj::Promise>> MessageStream::tryReadMessage( ReaderOptions options, kj::ArrayPtr scratchSpace) { return tryReadMessage(nullptr, options, scratchSpace) .then([](auto maybeReaderAndFds) -> kj::Maybe> { KJ_IF_MAYBE(readerAndFds, maybeReaderAndFds) { return kj::mv(readerAndFds->reader); } else { return nullptr; } }); } kj::Promise MessageStream::readMessage( kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { return tryReadMessage(fdSpace, options, scratchSpace).then([](auto maybeResult) { KJ_IF_MAYBE(result, maybeResult) { return kj::mv(*result); } else { kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "Premature EOF.")); KJ_UNREACHABLE; } }); } // ======================================================================================= class BufferedMessageStream::MessageReaderImpl: public FlatArrayMessageReader { public: MessageReaderImpl(BufferedMessageStream& parent, kj::ArrayPtr data, ReaderOptions options) : FlatArrayMessageReader(data, options), state(&parent) { KJ_DASSERT(!parent.hasOutstandingShortLivedMessage); parent.hasOutstandingShortLivedMessage = true; } MessageReaderImpl(kj::Array&& ownBuffer, ReaderOptions options) : FlatArrayMessageReader(ownBuffer, options), state(kj::mv(ownBuffer)) {} MessageReaderImpl(kj::ArrayPtr scratchBuffer, ReaderOptions options) : FlatArrayMessageReader(scratchBuffer, options) {} ~MessageReaderImpl() noexcept(false) { KJ_IF_MAYBE(parent, state.tryGet()) { (*parent)->hasOutstandingShortLivedMessage = false; } } private: kj::OneOf> state; // * BufferedMessageStream* if this reader aliases the original buffer. // * kj::Array if this reader owns its own backing buffer. }; BufferedMessageStream::BufferedMessageStream( kj::AsyncIoStream& stream, IsShortLivedCallback isShortLivedCallback, size_t bufferSizeInWords) : stream(stream), isShortLivedCallback(kj::mv(isShortLivedCallback)), buffer(kj::heapArray(bufferSizeInWords)), beginData(buffer.begin()), beginAvailable(buffer.asBytes().begin()) {} BufferedMessageStream::BufferedMessageStream( kj::AsyncCapabilityStream& stream, IsShortLivedCallback isShortLivedCallback, size_t bufferSizeInWords) : stream(stream), capStream(stream), isShortLivedCallback(kj::mv(isShortLivedCallback)), buffer(kj::heapArray(bufferSizeInWords)), beginData(buffer.begin()), beginAvailable(buffer.asBytes().begin()) {} kj::Promise> BufferedMessageStream::tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { return tryReadMessageImpl(fdSpace, 0, options, scratchSpace); } kj::Promise BufferedMessageStream::writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) { KJ_IF_MAYBE(cs, capStream) { return capnp::writeMessage(*cs, fds, segments); } else { return capnp::writeMessage(stream, segments); } } kj::Promise BufferedMessageStream::writeMessages( kj::ArrayPtr>> messages) { return capnp::writeMessages(stream, messages); } kj::Maybe BufferedMessageStream::getSendBufferSize() { return capnp::getSendBufferSize(stream); } kj::Promise BufferedMessageStream::end() { stream.shutdownWrite(); return kj::READY_NOW; } kj::Promise> BufferedMessageStream::tryReadMessageImpl( kj::ArrayPtr fdSpace, size_t fdsSoFar, ReaderOptions options, kj::ArrayPtr scratchSpace) { KJ_REQUIRE(!hasOutstandingShortLivedMessage, "can't read another message while the previous short-lived message still exists"); kj::byte* beginDataBytes = reinterpret_cast(beginData); size_t dataByteSize = beginAvailable - beginDataBytes; kj::ArrayPtr data = kj::arrayPtr(beginData, dataByteSize / sizeof(word)); size_t expected = expectedSizeInWordsFromPrefix(data); if (!leftoverFds.empty() && expected * sizeof(word) == dataByteSize) { // We're about to return a message that consumes the rest of the data in the buffer, and // `leftoverFds` is non-empty. Those FDs are considered attached to whatever message contains // the last byte in the buffer. That's us! Let's consume them. // `fdsSoFar` must be empty here because we shouldn't have performed any reads while // `leftoverFds` was non-empty, so there shouldn't have been any other chance to add FDs to // `fdSpace`. KJ_ASSERT(fdsSoFar == 0); fdsSoFar = kj::min(leftoverFds.size(), fdSpace.size()); for (auto i: kj::zeroTo(fdsSoFar)) { fdSpace[i] = kj::mv(leftoverFds[i]); } leftoverFds.clear(); } if (expected <= data.size()) { // The buffer contains at least one whole message, which we can just return without reading // any more data. auto msgData = kj::arrayPtr(beginData, expected); auto reader = kj::heap(*this, msgData, options); if (!isShortLivedCallback(*reader)) { // This message is long-lived, so we must make a copy to get it out of our buffer. if (msgData.size() <= scratchSpace.size()) { // Oh hey, we can use the provided scratch space. memcpy(scratchSpace.begin(), msgData.begin(), msgData.asBytes().size()); reader = kj::heap(scratchSpace, options); } else { auto ownMsgData = kj::heapArray(msgData.size()); memcpy(ownMsgData.begin(), msgData.begin(), msgData.asBytes().size()); reader = kj::heap(kj::mv(ownMsgData), options); } } beginData += expected; if (reinterpret_cast(beginData) == beginAvailable) { // The buffer is empty. Let's opportunistically reset the pointers. beginData = buffer.begin(); beginAvailable = buffer.asBytes().begin(); } else if (fdsSoFar > 0) { // The buffer is NOT empty, and we received FDs when we were filling it. These FDs must // actually belong to the last message in the buffer, because when the OS returns FDs // attached to a read, it will make sure the read does not extend past the last byte to // which those FDs were attached. // // So, we must set these FDs aside for the moment. for (auto i: kj::zeroTo(fdsSoFar)) { leftoverFds.add(kj::mv(fdSpace[i])); } fdsSoFar = 0; } return kj::Maybe(MessageReaderAndFds { kj::mv(reader), fdSpace.slice(0, fdsSoFar) }); } // At this point, the buffer doesn't contain a complete message. We are going to need to perform // a read. if (expected > buffer.size() / 2 || fdsSoFar > 0) { // Read this message into its own separately-allocated buffer. We do this for: // - Big messages, because they might not fit in the buffer and because big messages are // almost certainly going to be long-lived and so would require a copy later anyway. // - Messages where we've already received some FDs, because these are also almost certainly // long-lived, and we want to avoid accidentally reading into the next message since we // could end up receiving FDs that were intended for that one. // // Optimization note: You might argue that if the expected size is more than half the buffer, // but still less than the *whole* buffer, then we should still try to read into the buffer // first. However, keep in mind that in the RPC system, all short-lived messages are // relatively small, and hence we can assume that since this is a large message, it will // end up being long-lived. Long-lived messages need to be copied out into their own buffer // at some point anyway. So we might as well go ahead and allocate that separate buffer // now, and read directly into it, rather than try to use the shared buffer. We choose to // use buffer.size() / 2 as the cutoff because that ensures that we won't try to move the // bytes of a known-large message to the beginning of the buffer (see next if() after this // one). auto prefix = kj::arrayPtr(beginDataBytes, dataByteSize); // We are consuming everything in the buffer here, so we can reset the pointers so the // buffer appears empty on the next message read after this. beginData = buffer.begin(); beginAvailable = buffer.asBytes().begin(); return readEntireMessage(prefix, expected, fdSpace, fdsSoFar, options); } // Set minBytes to at least complete the current message. size_t minBytes = expected * sizeof(word) - dataByteSize; // minBytes must be less than half the buffer otherwise we would have taken the // readEntireMessage() branch above. KJ_DASSERT(minBytes <= buffer.asBytes().size() / 2); // Set maxBytes to the space we have available in the buffer. size_t maxBytes = buffer.asBytes().end() - beginAvailable; if (maxBytes < buffer.asBytes().size() / 2) { // We have less than half the buffer remaining to read into. Move the buffered data to the // beginning of the buffer to make more space. memmove(buffer.begin(), beginData, dataByteSize); beginData = buffer.begin(); beginDataBytes = buffer.asBytes().begin(); beginAvailable = beginDataBytes + dataByteSize; maxBytes = buffer.asBytes().end() - beginAvailable; } // maxBytes must now be more than half the buffer, because if it weren't we would have moved // the existing data above, and the existing data cannot be more than half the buffer because // if it were we would have taken the readEntireMesage() path earlier. KJ_DASSERT(maxBytes >= buffer.asBytes().size() / 2); // Since minBytes is less that half the buffer and maxBytes is more then half, minBytes is // definitely less than maxBytes. KJ_DASSERT(minBytes <= maxBytes); // Read from underlying stream. return tryReadWithFds(beginAvailable, minBytes, maxBytes, fdSpace.begin() + fdsSoFar, fdSpace.size() - fdsSoFar) .then([this,minBytes,fdSpace,fdsSoFar,options,scratchSpace] (kj::AsyncCapabilityStream::ReadResult result) mutable -> kj::Promise> { // Account for new data received in the buffer. beginAvailable += result.byteCount; if (result.byteCount < minBytes) { // Didn't reach minBytes, so we must have hit EOF. That's legal as long as it happened on // a clean message boundray. if (beginAvailable > reinterpret_cast(beginData)) { // We had received a partial message before EOF, so this should be considered an error. kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "stream disconnected prematurely")); } return kj::Maybe(nullptr); } // Loop! return tryReadMessageImpl(fdSpace, fdsSoFar + result.capCount, options, scratchSpace); }); } kj::Promise> BufferedMessageStream::readEntireMessage( kj::ArrayPtr prefix, size_t expectedSizeInWords, kj::ArrayPtr fdSpace, size_t fdsSoFar, ReaderOptions options) { KJ_REQUIRE(expectedSizeInWords <= options.traversalLimitInWords, "incoming RPC message exceeds size limit"); auto msgBuffer = kj::heapArray(expectedSizeInWords); memcpy(msgBuffer.asBytes().begin(), prefix.begin(), prefix.size()); size_t bytesRemaining = msgBuffer.asBytes().size() - prefix.size(); // TODO(perf): If we had scatter-read API support, we could optimistically try to read additional // bytes into the shared buffer, to save syscalls when a big message is immediately followed // by small messages. auto promise = tryReadWithFds( msgBuffer.asBytes().begin() + prefix.size(), bytesRemaining, bytesRemaining, fdSpace.begin() + fdsSoFar, fdSpace.size() - fdsSoFar); return promise .then([this, msgBuffer = kj::mv(msgBuffer), fdSpace, fdsSoFar, options, bytesRemaining] (kj::AsyncCapabilityStream::ReadResult result) mutable -> kj::Promise> { fdsSoFar += result.capCount; if (result.byteCount < bytesRemaining) { // Received EOF during message. kj::throwRecoverableException(KJ_EXCEPTION(DISCONNECTED, "stream disconnected prematurely")); return kj::Maybe(nullptr); } size_t newExpectedSize = expectedSizeInWordsFromPrefix(msgBuffer); if (newExpectedSize > msgBuffer.size()) { // Unfortunately, the predicted size increased. This can happen if the segment table had // not been fully received when we generated the first prediction. This should be rare // (most segment tables are small and should be received all at once), but in this case we // will need to make a whole new copy of the message. // // We recurse here, but this should never recurse more than once, since we should always // have the entire segment table by this point and therefore the expected size is now final. // // TODO(perf): Technically it's guaranteed that the original expectation should have stopped // at the boundary between two segments, so with a clever MesnsageReader implementation // we could actually read the rest of the message into a second buffer, avoiding the copy. // Unclear if it's worth the effort to implement this. return readEntireMessage(msgBuffer.asBytes(), newExpectedSize, fdSpace, fdsSoFar, options); } return kj::Maybe(MessageReaderAndFds { kj::heap(kj::mv(msgBuffer), options), fdSpace.slice(0, fdsSoFar) }); }); } kj::Promise BufferedMessageStream::tryReadWithFds( void* buffer, size_t minBytes, size_t maxBytes, kj::AutoCloseFd* fdBuffer, size_t maxFds) { KJ_IF_MAYBE(cs, capStream) { return cs->tryReadWithFds(buffer, minBytes, maxBytes, fdBuffer, maxFds); } else { // Regular byte stream, no FDs. return stream.tryRead(buffer, minBytes, maxBytes) .then([](size_t amount) mutable -> kj::AsyncCapabilityStream::ReadResult { return { amount, 0 }; }); } } } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc-twoparty.capnp.h0000644000175000017500000005413714731562162022577 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: rpc-twoparty.capnp #pragma once #include #include #if !CAPNP_LITE #include #endif // !CAPNP_LITE #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(9fd69ebc87b9719c); enum class Side_9fd69ebc87b9719c: uint16_t { SERVER, CLIENT, }; CAPNP_DECLARE_ENUM(Side, 9fd69ebc87b9719c); CAPNP_DECLARE_SCHEMA(d20b909fee733a8e); CAPNP_DECLARE_SCHEMA(b88d09a9c5f39817); CAPNP_DECLARE_SCHEMA(89f389b6fd4082c1); CAPNP_DECLARE_SCHEMA(b47f4979672cb59d); CAPNP_DECLARE_SCHEMA(95b29059097fca83); CAPNP_DECLARE_SCHEMA(9d263a3630b7ebee); } // namespace schemas } // namespace capnp namespace capnp { namespace rpc { namespace twoparty { typedef ::capnp::schemas::Side_9fd69ebc87b9719c Side; struct VatId { VatId() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d20b909fee733a8e, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct ProvisionId { ProvisionId() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b88d09a9c5f39817, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct RecipientId { RecipientId() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(89f389b6fd4082c1, 0, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct ThirdPartyCapId { ThirdPartyCapId() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b47f4979672cb59d, 0, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct JoinKeyPart { JoinKeyPart() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(95b29059097fca83, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct JoinResult { JoinResult() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9d263a3630b7ebee, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class VatId::Reader { public: typedef VatId Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::capnp::rpc::twoparty::Side getSide() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class VatId::Builder { public: typedef VatId Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::capnp::rpc::twoparty::Side getSide(); inline void setSide( ::capnp::rpc::twoparty::Side value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class VatId::Pipeline { public: typedef VatId Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class ProvisionId::Reader { public: typedef ProvisionId Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class ProvisionId::Builder { public: typedef ProvisionId Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId(); inline void setJoinId( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class ProvisionId::Pipeline { public: typedef ProvisionId Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class RecipientId::Reader { public: typedef RecipientId Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class RecipientId::Builder { public: typedef RecipientId Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class RecipientId::Pipeline { public: typedef RecipientId Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class ThirdPartyCapId::Reader { public: typedef ThirdPartyCapId Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class ThirdPartyCapId::Builder { public: typedef ThirdPartyCapId Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class ThirdPartyCapId::Pipeline { public: typedef ThirdPartyCapId Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class JoinKeyPart::Reader { public: typedef JoinKeyPart Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId() const; inline ::uint16_t getPartCount() const; inline ::uint16_t getPartNum() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class JoinKeyPart::Builder { public: typedef JoinKeyPart Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId(); inline void setJoinId( ::uint32_t value); inline ::uint16_t getPartCount(); inline void setPartCount( ::uint16_t value); inline ::uint16_t getPartNum(); inline void setPartNum( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class JoinKeyPart::Pipeline { public: typedef JoinKeyPart Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class JoinResult::Reader { public: typedef JoinResult Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId() const; inline bool getSucceeded() const; inline bool hasCap() const; #if !CAPNP_LITE inline ::capnp::Capability::Client getCap() const; #endif // !CAPNP_LITE private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class JoinResult::Builder { public: typedef JoinResult Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getJoinId(); inline void setJoinId( ::uint32_t value); inline bool getSucceeded(); inline void setSucceeded(bool value); inline bool hasCap(); #if !CAPNP_LITE inline ::capnp::Capability::Client getCap(); inline void setCap( ::capnp::Capability::Client&& value); inline void setCap( ::capnp::Capability::Client& value); inline void adoptCap(::capnp::Orphan< ::capnp::Capability>&& value); inline ::capnp::Orphan< ::capnp::Capability> disownCap(); #endif // !CAPNP_LITE private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class JoinResult::Pipeline { public: typedef JoinResult Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::Capability::Client getCap(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline ::capnp::rpc::twoparty::Side VatId::Reader::getSide() const { return _reader.getDataField< ::capnp::rpc::twoparty::Side>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::twoparty::Side VatId::Builder::getSide() { return _builder.getDataField< ::capnp::rpc::twoparty::Side>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void VatId::Builder::setSide( ::capnp::rpc::twoparty::Side value) { _builder.setDataField< ::capnp::rpc::twoparty::Side>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t ProvisionId::Reader::getJoinId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t ProvisionId::Builder::getJoinId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void ProvisionId::Builder::setJoinId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t JoinKeyPart::Reader::getJoinId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t JoinKeyPart::Builder::getJoinId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void JoinKeyPart::Builder::setJoinId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint16_t JoinKeyPart::Reader::getPartCount() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint16_t JoinKeyPart::Builder::getPartCount() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void JoinKeyPart::Builder::setPartCount( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint16_t JoinKeyPart::Reader::getPartNum() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint16_t JoinKeyPart::Builder::getPartNum() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline void JoinKeyPart::Builder::setPartNum( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); } inline ::uint32_t JoinResult::Reader::getJoinId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t JoinResult::Builder::getJoinId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void JoinResult::Builder::setJoinId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool JoinResult::Reader::getSucceeded() const { return _reader.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS); } inline bool JoinResult::Builder::getSucceeded() { return _builder.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS); } inline void JoinResult::Builder::setSucceeded(bool value) { _builder.setDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, value); } inline bool JoinResult::Reader::hasCap() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool JoinResult::Builder::hasCap() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } #if !CAPNP_LITE inline ::capnp::Capability::Client JoinResult::Reader::getCap() const { return ::capnp::_::PointerHelpers< ::capnp::Capability>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Capability::Client JoinResult::Builder::getCap() { return ::capnp::_::PointerHelpers< ::capnp::Capability>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Capability::Client JoinResult::Pipeline::getCap() { return ::capnp::Capability::Client(_typeless.getPointerField(0).asCap()); } inline void JoinResult::Builder::setCap( ::capnp::Capability::Client&& cap) { ::capnp::_::PointerHelpers< ::capnp::Capability>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(cap)); } inline void JoinResult::Builder::setCap( ::capnp::Capability::Client& cap) { ::capnp::_::PointerHelpers< ::capnp::Capability>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), cap); } inline void JoinResult::Builder::adoptCap( ::capnp::Orphan< ::capnp::Capability>&& value) { ::capnp::_::PointerHelpers< ::capnp::Capability>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Capability> JoinResult::Builder::disownCap() { return ::capnp::_::PointerHelpers< ::capnp::Capability>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #endif // !CAPNP_LITE } // namespace } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/dynamic.c++0000644000175000017500000023057414731420004020556 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "dynamic.h" #include namespace capnp { namespace { bool hasDiscriminantValue(const schema::Field::Reader& reader) { return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; } template KJ_ALWAYS_INLINE(T bitCast(U value)); template inline T bitCast(U value) { static_assert(sizeof(T) == sizeof(U), "Size must match."); return value; } template <> inline float bitCast(uint32_t value) KJ_UNUSED; template <> inline float bitCast(uint32_t value) { float result; memcpy(&result, &value, sizeof(value)); return result; } template <> inline double bitCast(uint64_t value) KJ_UNUSED; template <> inline double bitCast(uint64_t value) { double result; memcpy(&result, &value, sizeof(value)); return result; } template <> inline uint32_t bitCast(float value) { uint32_t result; memcpy(&result, &value, sizeof(value)); return result; } template <> inline uint64_t bitCast(double value) { uint64_t result; memcpy(&result, &value, sizeof(value)); return result; } ElementSize elementSizeFor(schema::Type::Which elementType) { switch (elementType) { case schema::Type::VOID: return ElementSize::VOID; case schema::Type::BOOL: return ElementSize::BIT; case schema::Type::INT8: return ElementSize::BYTE; case schema::Type::INT16: return ElementSize::TWO_BYTES; case schema::Type::INT32: return ElementSize::FOUR_BYTES; case schema::Type::INT64: return ElementSize::EIGHT_BYTES; case schema::Type::UINT8: return ElementSize::BYTE; case schema::Type::UINT16: return ElementSize::TWO_BYTES; case schema::Type::UINT32: return ElementSize::FOUR_BYTES; case schema::Type::UINT64: return ElementSize::EIGHT_BYTES; case schema::Type::FLOAT32: return ElementSize::FOUR_BYTES; case schema::Type::FLOAT64: return ElementSize::EIGHT_BYTES; case schema::Type::TEXT: return ElementSize::POINTER; case schema::Type::DATA: return ElementSize::POINTER; case schema::Type::LIST: return ElementSize::POINTER; case schema::Type::ENUM: return ElementSize::TWO_BYTES; case schema::Type::STRUCT: return ElementSize::INLINE_COMPOSITE; case schema::Type::INTERFACE: return ElementSize::POINTER; case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported."); break; } // Unknown type. Treat it as zero-size. return ElementSize::VOID; } inline _::StructSize structSizeFromSchema(StructSchema schema) { auto node = schema.getProto().getStruct(); return _::StructSize( bounded(node.getDataWordCount()) * WORDS, bounded(node.getPointerCount()) * POINTERS); } } // namespace // ======================================================================================= kj::Maybe DynamicEnum::getEnumerant() const { auto enumerants = schema.getEnumerants(); if (value < enumerants.size()) { return enumerants[value]; } else { return nullptr; } } uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) const { KJ_REQUIRE(requestedTypeId == schema.getProto().getId(), "Type mismatch in DynamicEnum.as().") { // use it anyway break; } return value; } // ======================================================================================= bool DynamicStruct::Reader::isSetInUnion(StructSchema::Field field) const { auto proto = field.getProto(); if (hasDiscriminantValue(proto)) { uint16_t discrim = reader.getDataField( assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); return discrim == proto.getDiscriminantValue(); } else { return true; } } void DynamicStruct::Reader::verifySetInUnion(StructSchema::Field field) const { KJ_REQUIRE(isSetInUnion(field), "Tried to get() a union member which is not currently initialized.", field.getProto().getName(), schema.getProto().getDisplayName()); } bool DynamicStruct::Builder::isSetInUnion(StructSchema::Field field) { auto proto = field.getProto(); if (hasDiscriminantValue(proto)) { uint16_t discrim = builder.getDataField( assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); return discrim == proto.getDiscriminantValue(); } else { return true; } } void DynamicStruct::Builder::verifySetInUnion(StructSchema::Field field) { KJ_REQUIRE(isSetInUnion(field), "Tried to get() a union member which is not currently initialized.", field.getProto().getName(), schema.getProto().getDisplayName()); } void DynamicStruct::Builder::setInUnion(StructSchema::Field field) { // If a union member, set the discriminant to match. auto proto = field.getProto(); if (hasDiscriminantValue(proto)) { builder.setDataField( assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset()), proto.getDiscriminantValue()); } } DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); verifySetInUnion(field); auto type = field.getType(); auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); // Note that the default value might be "anyPointer" even if the type is some pointer type // *other than* anyPointer. This happens with generics -- the field is actually a generic // parameter that has been bound, but the default value was of course compiled without any // binding available. auto dval = slot.getDefaultValue(); switch (type.which()) { case schema::Type::VOID: return reader.getDataField(assumeDataOffset(slot.getOffset())); #define HANDLE_TYPE(discrim, titleCase, type) \ case schema::Type::discrim: \ return reader.getDataField( \ assumeDataOffset(slot.getOffset()), \ bitCast<_::Mask>(dval.get##titleCase())); HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(INT8, Int8, int8_t) HANDLE_TYPE(INT16, Int16, int16_t) HANDLE_TYPE(INT32, Int32, int32_t) HANDLE_TYPE(INT64, Int64, int64_t) HANDLE_TYPE(UINT8, Uint8, uint8_t) HANDLE_TYPE(UINT16, Uint16, uint16_t) HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(FLOAT64, Float64, double) #undef HANDLE_TYPE case schema::Type::ENUM: { uint16_t typedDval = dval.getEnum(); return DynamicEnum(type.asEnum(), reader.getDataField(assumeDataOffset(slot.getOffset()), typedDval)); } case schema::Type::TEXT: { Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); return reader.getPointerField(assumePointerOffset(slot.getOffset())) .getBlob(typedDval.begin(), assumeMax(typedDval.size()) * BYTES); } case schema::Type::DATA: { Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); return reader.getPointerField(assumePointerOffset(slot.getOffset())) .getBlob(typedDval.begin(), assumeBits(typedDval.size()) * BYTES); } case schema::Type::LIST: { auto elementType = type.asList().getElementType(); return DynamicList::Reader(type.asList(), reader.getPointerField(assumePointerOffset(slot.getOffset())) .getList(elementSizeFor(elementType.which()), dval.isAnyPointer() ? nullptr : dval.getList().getAs<_::UncheckedMessage>())); } case schema::Type::STRUCT: return DynamicStruct::Reader(type.asStruct(), reader.getPointerField(assumePointerOffset(slot.getOffset())) .getStruct(dval.isAnyPointer() ? nullptr : dval.getStruct().getAs<_::UncheckedMessage>())); case schema::Type::ANY_POINTER: return AnyPointer::Reader(reader.getPointerField(assumePointerOffset(slot.getOffset()))); case schema::Type::INTERFACE: return DynamicCapability::Client(type.asInterface(), reader.getPointerField(assumePointerOffset(slot.getOffset())).getCapability()); } KJ_UNREACHABLE; } case schema::Field::GROUP: return DynamicStruct::Reader(type.asStruct(), reader); } KJ_UNREACHABLE; } DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); verifySetInUnion(field); auto proto = field.getProto(); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); // Note that the default value might be "anyPointer" even if the type is some pointer type // *other than* anyPointer. This happens with generics -- the field is actually a generic // parameter that has been bound, but the default value was of course compiled without any // binding available. auto dval = slot.getDefaultValue(); switch (type.which()) { case schema::Type::VOID: return builder.getDataField(assumeDataOffset(slot.getOffset())); #define HANDLE_TYPE(discrim, titleCase, type) \ case schema::Type::discrim: \ return builder.getDataField( \ assumeDataOffset(slot.getOffset()), \ bitCast<_::Mask>(dval.get##titleCase())); HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(INT8, Int8, int8_t) HANDLE_TYPE(INT16, Int16, int16_t) HANDLE_TYPE(INT32, Int32, int32_t) HANDLE_TYPE(INT64, Int64, int64_t) HANDLE_TYPE(UINT8, Uint8, uint8_t) HANDLE_TYPE(UINT16, Uint16, uint16_t) HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(FLOAT64, Float64, double) #undef HANDLE_TYPE case schema::Type::ENUM: { uint16_t typedDval = dval.getEnum(); return DynamicEnum(type.asEnum(), builder.getDataField(assumeDataOffset(slot.getOffset()), typedDval)); } case schema::Type::TEXT: { Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); return builder.getPointerField(assumePointerOffset(slot.getOffset())) .getBlob(typedDval.begin(), assumeMax(typedDval.size()) * BYTES); } case schema::Type::DATA: { Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); return builder.getPointerField(assumePointerOffset(slot.getOffset())) .getBlob(typedDval.begin(), assumeBits(typedDval.size()) * BYTES); } case schema::Type::LIST: { ListSchema listType = type.asList(); if (listType.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(listType, builder.getPointerField(assumePointerOffset(slot.getOffset())) .getStructList(structSizeFromSchema(listType.getStructElementType()), dval.isAnyPointer() ? nullptr : dval.getList().getAs<_::UncheckedMessage>())); } else { return DynamicList::Builder(listType, builder.getPointerField(assumePointerOffset(slot.getOffset())) .getList(elementSizeFor(listType.whichElementType()), dval.isAnyPointer() ? nullptr : dval.getList().getAs<_::UncheckedMessage>())); } } case schema::Type::STRUCT: { auto structSchema = type.asStruct(); return DynamicStruct::Builder(structSchema, builder.getPointerField(assumePointerOffset(slot.getOffset())) .getStruct(structSizeFromSchema(structSchema), dval.isAnyPointer() ? nullptr : dval.getStruct().getAs<_::UncheckedMessage>())); } case schema::Type::ANY_POINTER: return AnyPointer::Builder( builder.getPointerField(assumePointerOffset(slot.getOffset()))); case schema::Type::INTERFACE: return DynamicCapability::Client(type.asInterface(), builder.getPointerField(assumePointerOffset(slot.getOffset())).getCapability()); } KJ_UNREACHABLE; } case schema::Field::GROUP: return DynamicStruct::Builder(type.asStruct(), builder); } KJ_UNREACHABLE; } DynamicValue::Pipeline DynamicStruct::Pipeline::get(StructSchema::Field field) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); auto proto = field.getProto(); KJ_REQUIRE(!hasDiscriminantValue(proto), "Can't pipeline on union members."); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); switch (type.which()) { case schema::Type::STRUCT: return DynamicStruct::Pipeline(type.asStruct(), typeless.getPointerField(slot.getOffset())); case schema::Type::INTERFACE: return DynamicCapability::Client(type.asInterface(), typeless.getPointerField(slot.getOffset()).asCap()); case schema::Type::ANY_POINTER: switch (type.whichAnyPointerKind()) { case schema::Type::AnyPointer::Unconstrained::STRUCT: return DynamicStruct::Pipeline(StructSchema(), typeless.getPointerField(slot.getOffset())); case schema::Type::AnyPointer::Unconstrained::CAPABILITY: return DynamicCapability::Client(Capability::Client( typeless.getPointerField(slot.getOffset()).asCap())); default: KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields."); } default: KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields."); } KJ_UNREACHABLE; } case schema::Field::GROUP: return DynamicStruct::Pipeline(type.asStruct(), typeless.noop()); } KJ_UNREACHABLE; } bool DynamicStruct::Reader::has(StructSchema::Field field, HasMode mode) const { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); auto proto = field.getProto(); if (hasDiscriminantValue(proto)) { uint16_t discrim = reader.getDataField( assumeDataOffset(schema.getProto().getStruct().getDiscriminantOffset())); if (discrim != proto.getDiscriminantValue()) { // Field is not active in the union. return false; } } switch (proto.which()) { case schema::Field::SLOT: // Continue to below. break; case schema::Field::GROUP: return true; } auto slot = proto.getSlot(); auto type = field.getType(); switch (type.which()) { case schema::Type::VOID: // Void is always equal to the default. return mode == HasMode::NON_NULL; case schema::Type::BOOL: return mode == HasMode::NON_NULL || reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; case schema::Type::INT8: case schema::Type::UINT8: return mode == HasMode::NON_NULL || reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; case schema::Type::INT16: case schema::Type::UINT16: case schema::Type::ENUM: return mode == HasMode::NON_NULL || reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; case schema::Type::INT32: case schema::Type::UINT32: case schema::Type::FLOAT32: return mode == HasMode::NON_NULL || reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; case schema::Type::INT64: case schema::Type::UINT64: case schema::Type::FLOAT64: return mode == HasMode::NON_NULL || reader.getDataField(assumeDataOffset(slot.getOffset()), 0) != 0; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::ANY_POINTER: case schema::Type::INTERFACE: return !reader.getPointerField(assumePointerOffset(slot.getOffset())).isNull(); } // Unknown type. As far as we know, it isn't set. return false; } kj::Maybe DynamicStruct::Reader::which() const { auto structProto = schema.getProto().getStruct(); if (structProto.getDiscriminantCount() == 0) { return nullptr; } uint16_t discrim = reader.getDataField( assumeDataOffset(structProto.getDiscriminantOffset())); return schema.getFieldByDiscriminant(discrim); } kj::Maybe DynamicStruct::Builder::which() { auto structProto = schema.getProto().getStruct(); if (structProto.getDiscriminantCount() == 0) { return nullptr; } uint16_t discrim = builder.getDataField( assumeDataOffset(structProto.getDiscriminantOffset())); return schema.getFieldByDiscriminant(discrim); } void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue::Reader& value) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); setInUnion(field); auto proto = field.getProto(); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); auto dval = slot.getDefaultValue(); switch (type.which()) { case schema::Type::VOID: builder.setDataField(assumeDataOffset(slot.getOffset()), value.as()); return; #define HANDLE_TYPE(discrim, titleCase, type) \ case schema::Type::discrim: \ builder.setDataField( \ assumeDataOffset(slot.getOffset()), value.as(), \ bitCast<_::Mask >(dval.get##titleCase())); \ return; HANDLE_TYPE(BOOL, Bool, bool) HANDLE_TYPE(INT8, Int8, int8_t) HANDLE_TYPE(INT16, Int16, int16_t) HANDLE_TYPE(INT32, Int32, int32_t) HANDLE_TYPE(INT64, Int64, int64_t) HANDLE_TYPE(UINT8, Uint8, uint8_t) HANDLE_TYPE(UINT16, Uint16, uint16_t) HANDLE_TYPE(UINT32, Uint32, uint32_t) HANDLE_TYPE(UINT64, Uint64, uint64_t) HANDLE_TYPE(FLOAT32, Float32, float) HANDLE_TYPE(FLOAT64, Float64, double) #undef HANDLE_TYPE case schema::Type::ENUM: { uint16_t rawValue; auto enumSchema = type.asEnum(); if (value.getType() == DynamicValue::TEXT) { // Convert from text. rawValue = enumSchema.getEnumerantByName(value.as()).getOrdinal(); } else if (value.getType() == DynamicValue::INT || value.getType() == DynamicValue::UINT) { rawValue = value.as(); } else { DynamicEnum enumValue = value.as(); KJ_REQUIRE(enumValue.getSchema() == enumSchema, "Value type mismatch.") { return; } rawValue = enumValue.getRaw(); } builder.setDataField(assumeDataOffset(slot.getOffset()), rawValue, dval.getEnum()); return; } case schema::Type::TEXT: builder.getPointerField(assumePointerOffset(slot.getOffset())) .setBlob(value.as()); return; case schema::Type::DATA: builder.getPointerField(assumePointerOffset(slot.getOffset())) .setBlob(value.as()); return; case schema::Type::LIST: { ListSchema listType = type.asList(); auto listValue = value.as(); KJ_REQUIRE(listValue.getSchema() == listType, "Value type mismatch.") { return; } builder.getPointerField(assumePointerOffset(slot.getOffset())) .setList(listValue.reader); return; } case schema::Type::STRUCT: { auto structType = type.asStruct(); auto structValue = value.as(); KJ_REQUIRE(structValue.getSchema() == structType, "Value type mismatch.") { return; } builder.getPointerField(assumePointerOffset(slot.getOffset())) .setStruct(structValue.reader); return; } case schema::Type::ANY_POINTER: { auto target = AnyPointer::Builder( builder.getPointerField(assumePointerOffset(slot.getOffset()))); switch (value.getType()) { case DynamicValue::Type::TEXT: target.setAs(value.as()); return; case DynamicValue::Type::DATA: target.setAs(value.as()); return; case DynamicValue::Type::LIST: target.setAs(value.as()); return; case DynamicValue::Type::STRUCT: target.setAs(value.as()); return; case DynamicValue::Type::CAPABILITY: target.setAs(value.as()); return; case DynamicValue::Type::ANY_POINTER: target.set(value.as()); return; case DynamicValue::Type::UNKNOWN: case DynamicValue::Type::VOID: case DynamicValue::Type::BOOL: case DynamicValue::Type::INT: case DynamicValue::Type::UINT: case DynamicValue::Type::FLOAT: case DynamicValue::Type::ENUM: KJ_FAIL_ASSERT("Value type mismatch; expected AnyPointer"); } KJ_UNREACHABLE; } case schema::Type::INTERFACE: { auto interfaceType = type.asInterface(); auto capability = value.as(); KJ_REQUIRE(capability.getSchema().extends(interfaceType), "Value type mismatch.") { return; } builder.getPointerField(assumePointerOffset(slot.getOffset())) .setCapability(kj::mv(capability.hook)); return; } } KJ_UNREACHABLE; } case schema::Field::GROUP: { auto src = value.as(); auto dst = init(field).as(); KJ_IF_MAYBE(unionField, src.which()) { dst.set(*unionField, src.get(*unionField)); } for (auto field: src.schema.getNonUnionFields()) { if (src.has(field)) { dst.set(field, src.get(field)); } } return; } } KJ_UNREACHABLE; } DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); setInUnion(field); auto proto = field.getProto(); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); switch (type.which()) { case schema::Type::STRUCT: { auto subSchema = type.asStruct(); return DynamicStruct::Builder(subSchema, builder.getPointerField(assumePointerOffset(slot.getOffset())) .initStruct(structSizeFromSchema(subSchema))); } case schema::Type::ANY_POINTER: { auto pointer = builder.getPointerField(assumePointerOffset(slot.getOffset())); pointer.clear(); return AnyPointer::Builder(pointer); } default: KJ_FAIL_REQUIRE("init() without a size is only valid for struct and object fields."); } } case schema::Field::GROUP: { clear(field); return DynamicStruct::Builder(type.asStruct(), builder); } } KJ_UNREACHABLE; } DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field, uint size) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); setInUnion(field); auto proto = field.getProto(); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); switch (type.which()) { case schema::Type::LIST: { auto listType = type.asList(); if (listType.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(listType, builder.getPointerField(assumePointerOffset(slot.getOffset())) .initStructList(bounded(size) * ELEMENTS, structSizeFromSchema(listType.getStructElementType()))); } else { return DynamicList::Builder(listType, builder.getPointerField(assumePointerOffset(slot.getOffset())) .initList(elementSizeFor(listType.whichElementType()), bounded(size) * ELEMENTS)); } } case schema::Type::TEXT: return builder.getPointerField(assumePointerOffset(slot.getOffset())) .initBlob(bounded(size) * BYTES); case schema::Type::DATA: return builder.getPointerField(assumePointerOffset(slot.getOffset())) .initBlob(bounded(size) * BYTES); default: KJ_FAIL_REQUIRE( "init() with size is only valid for list, text, or data fields.", (uint)type.which()); break; } KJ_UNREACHABLE; } case schema::Field::GROUP: KJ_FAIL_REQUIRE("init() with size is only valid for list, text, or data fields."); } KJ_UNREACHABLE; } void DynamicStruct::Builder::adopt(StructSchema::Field field, Orphan&& orphan) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); setInUnion(field); auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); auto type = field.getType(); switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: set(field, orphan.getReader()); return; case schema::Type::TEXT: KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); break; case schema::Type::DATA: KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); break; case schema::Type::LIST: { ListSchema listType = type.asList(); KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == listType, "Value type mismatch.") { return; } break; } case schema::Type::STRUCT: { auto structType = type.asStruct(); KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == structType, "Value type mismatch.") { return; } break; } case schema::Type::ANY_POINTER: KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT || orphan.getType() == DynamicValue::LIST || orphan.getType() == DynamicValue::TEXT || orphan.getType() == DynamicValue::DATA || orphan.getType() == DynamicValue::CAPABILITY || orphan.getType() == DynamicValue::ANY_POINTER, "Value type mismatch.") { return; } break; case schema::Type::INTERFACE: { auto interfaceType = type.asInterface(); KJ_REQUIRE(orphan.getType() == DynamicValue::CAPABILITY && orphan.interfaceSchema.extends(interfaceType), "Value type mismatch.") { return; } break; } } builder.getPointerField(assumePointerOffset(slot.getOffset())).adopt(kj::mv(orphan.builder)); return; } case schema::Field::GROUP: // Have to transfer fields. auto src = orphan.get().as(); auto dst = init(field).as(); KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == dst.getSchema(), "Value type mismatch."); KJ_IF_MAYBE(unionField, src.which()) { dst.adopt(*unionField, src.disown(*unionField)); } for (auto field: src.schema.getNonUnionFields()) { if (src.has(field)) { dst.adopt(field, src.disown(field)); } } return; } KJ_UNREACHABLE; } Orphan DynamicStruct::Builder::disown(StructSchema::Field field) { // We end up calling get(field) below, so we don't need to validate `field` here. auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); switch (field.getType().which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: { auto result = Orphan(get(field), _::OrphanBuilder()); clear(field); return kj::mv(result); } case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::ANY_POINTER: case schema::Type::INTERFACE: { auto value = get(field); return Orphan( value, builder.getPointerField(assumePointerOffset(slot.getOffset())).disown()); } } KJ_UNREACHABLE; } case schema::Field::GROUP: { // We have to allocate new space for the group, unfortunately. auto src = get(field).as(); Orphan result = Orphanage::getForMessageContaining(*this).newOrphan(src.getSchema()); auto dst = result.get(); KJ_IF_MAYBE(unionField, src.which()) { dst.adopt(*unionField, src.disown(*unionField)); } // We need to explicitly reset the union to its default field. KJ_IF_MAYBE(unionField, src.schema.getFieldByDiscriminant(0)) { src.clear(*unionField); } for (auto field: src.schema.getNonUnionFields()) { if (src.has(field)) { dst.adopt(field, src.disown(field)); } } return kj::mv(result); } } KJ_UNREACHABLE; } void DynamicStruct::Builder::clear(StructSchema::Field field) { KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); setInUnion(field); auto proto = field.getProto(); auto type = field.getType(); switch (proto.which()) { case schema::Field::SLOT: { auto slot = proto.getSlot(); switch (type.which()) { case schema::Type::VOID: builder.setDataField(assumeDataOffset(slot.getOffset()), VOID); return; #define HANDLE_TYPE(discrim, type) \ case schema::Type::discrim: \ builder.setDataField(assumeDataOffset(slot.getOffset()), 0); \ return; HANDLE_TYPE(BOOL, bool) HANDLE_TYPE(INT8, uint8_t) HANDLE_TYPE(INT16, uint16_t) HANDLE_TYPE(INT32, uint32_t) HANDLE_TYPE(INT64, uint64_t) HANDLE_TYPE(UINT8, uint8_t) HANDLE_TYPE(UINT16, uint16_t) HANDLE_TYPE(UINT32, uint32_t) HANDLE_TYPE(UINT64, uint64_t) HANDLE_TYPE(FLOAT32, uint32_t) HANDLE_TYPE(FLOAT64, uint64_t) HANDLE_TYPE(ENUM, uint16_t) #undef HANDLE_TYPE case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::ANY_POINTER: case schema::Type::INTERFACE: builder.getPointerField(assumePointerOffset(slot.getOffset())).clear(); return; } KJ_UNREACHABLE; } case schema::Field::GROUP: { DynamicStruct::Builder group(type.asStruct(), builder); // We clear the union field with discriminant 0 rather than the one that is set because // we want the union to end up with its default field active. KJ_IF_MAYBE(unionField, group.schema.getFieldByDiscriminant(0)) { group.clear(*unionField); } for (auto subField: group.schema.getNonUnionFields()) { group.clear(subField); } return; } } KJ_UNREACHABLE; } DynamicValue::Reader DynamicStruct::Reader::get(kj::StringPtr name) const { return get(schema.getFieldByName(name)); } DynamicValue::Builder DynamicStruct::Builder::get(kj::StringPtr name) { return get(schema.getFieldByName(name)); } DynamicValue::Pipeline DynamicStruct::Pipeline::get(kj::StringPtr name) { return get(schema.getFieldByName(name)); } bool DynamicStruct::Reader::has(kj::StringPtr name, HasMode mode) const { return has(schema.getFieldByName(name), mode); } bool DynamicStruct::Builder::has(kj::StringPtr name, HasMode mode) { return has(schema.getFieldByName(name), mode); } void DynamicStruct::Builder::set(kj::StringPtr name, const DynamicValue::Reader& value) { set(schema.getFieldByName(name), value); } void DynamicStruct::Builder::set(kj::StringPtr name, std::initializer_list value) { auto list = init(name, value.size()).as(); uint i = 0; for (auto element: value) { list.set(i++, element); } } DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name) { return init(schema.getFieldByName(name)); } DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name, uint size) { return init(schema.getFieldByName(name), size); } void DynamicStruct::Builder::adopt(kj::StringPtr name, Orphan&& orphan) { adopt(schema.getFieldByName(name), kj::mv(orphan)); } Orphan DynamicStruct::Builder::disown(kj::StringPtr name) { return disown(schema.getFieldByName(name)); } void DynamicStruct::Builder::clear(kj::StringPtr name) { clear(schema.getFieldByName(name)); } // ======================================================================================= DynamicValue::Reader DynamicList::Reader::operator[](uint index) const { KJ_REQUIRE(index < size(), "List index out-of-bounds."); switch (schema.whichElementType()) { #define HANDLE_TYPE(name, discrim, typeName) \ case schema::Type::discrim: \ return reader.getDataElement(bounded(index) * ELEMENTS); HANDLE_TYPE(void, VOID, Void) HANDLE_TYPE(bool, BOOL, bool) HANDLE_TYPE(int8, INT8, int8_t) HANDLE_TYPE(int16, INT16, int16_t) HANDLE_TYPE(int32, INT32, int32_t) HANDLE_TYPE(int64, INT64, int64_t) HANDLE_TYPE(uint8, UINT8, uint8_t) HANDLE_TYPE(uint16, UINT16, uint16_t) HANDLE_TYPE(uint32, UINT32, uint32_t) HANDLE_TYPE(uint64, UINT64, uint64_t) HANDLE_TYPE(float32, FLOAT32, float) HANDLE_TYPE(float64, FLOAT64, double) #undef HANDLE_TYPE case schema::Type::TEXT: return reader.getPointerElement(bounded(index) * ELEMENTS) .getBlob(nullptr, ZERO * BYTES); case schema::Type::DATA: return reader.getPointerElement(bounded(index) * ELEMENTS) .getBlob(nullptr, ZERO * BYTES); case schema::Type::LIST: { auto elementType = schema.getListElementType(); return DynamicList::Reader(elementType, reader.getPointerElement(bounded(index) * ELEMENTS) .getList(elementSizeFor(elementType.whichElementType()), nullptr)); } case schema::Type::STRUCT: return DynamicStruct::Reader(schema.getStructElementType(), reader.getStructElement(bounded(index) * ELEMENTS)); case schema::Type::ENUM: return DynamicEnum(schema.getEnumElementType(), reader.getDataElement(bounded(index) * ELEMENTS)); case schema::Type::ANY_POINTER: return AnyPointer::Reader(reader.getPointerElement(bounded(index) * ELEMENTS)); case schema::Type::INTERFACE: return DynamicCapability::Client(schema.getInterfaceElementType(), reader.getPointerElement(bounded(index) * ELEMENTS) .getCapability()); } return nullptr; } DynamicValue::Builder DynamicList::Builder::operator[](uint index) { KJ_REQUIRE(index < size(), "List index out-of-bounds."); switch (schema.whichElementType()) { #define HANDLE_TYPE(name, discrim, typeName) \ case schema::Type::discrim: \ return builder.getDataElement(bounded(index) * ELEMENTS); HANDLE_TYPE(void, VOID, Void) HANDLE_TYPE(bool, BOOL, bool) HANDLE_TYPE(int8, INT8, int8_t) HANDLE_TYPE(int16, INT16, int16_t) HANDLE_TYPE(int32, INT32, int32_t) HANDLE_TYPE(int64, INT64, int64_t) HANDLE_TYPE(uint8, UINT8, uint8_t) HANDLE_TYPE(uint16, UINT16, uint16_t) HANDLE_TYPE(uint32, UINT32, uint32_t) HANDLE_TYPE(uint64, UINT64, uint64_t) HANDLE_TYPE(float32, FLOAT32, float) HANDLE_TYPE(float64, FLOAT64, double) #undef HANDLE_TYPE case schema::Type::TEXT: return builder.getPointerElement(bounded(index) * ELEMENTS) .getBlob(nullptr, ZERO * BYTES); case schema::Type::DATA: return builder.getPointerElement(bounded(index) * ELEMENTS) .getBlob(nullptr, ZERO * BYTES); case schema::Type::LIST: { ListSchema elementType = schema.getListElementType(); if (elementType.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(elementType, builder.getPointerElement(bounded(index) * ELEMENTS) .getStructList(structSizeFromSchema(elementType.getStructElementType()), nullptr)); } else { return DynamicList::Builder(elementType, builder.getPointerElement(bounded(index) * ELEMENTS) .getList(elementSizeFor(elementType.whichElementType()), nullptr)); } } case schema::Type::STRUCT: return DynamicStruct::Builder(schema.getStructElementType(), builder.getStructElement(bounded(index) * ELEMENTS)); case schema::Type::ENUM: return DynamicEnum(schema.getEnumElementType(), builder.getDataElement(bounded(index) * ELEMENTS)); case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported."); return nullptr; case schema::Type::INTERFACE: return DynamicCapability::Client(schema.getInterfaceElementType(), builder.getPointerElement(bounded(index) * ELEMENTS) .getCapability()); } return nullptr; } void DynamicList::Builder::set(uint index, const DynamicValue::Reader& value) { KJ_REQUIRE(index < size(), "List index out-of-bounds.") { return; } switch (schema.whichElementType()) { #define HANDLE_TYPE(name, discrim, typeName) \ case schema::Type::discrim: \ builder.setDataElement(bounded(index) * ELEMENTS, value.as()); \ return; HANDLE_TYPE(void, VOID, Void) HANDLE_TYPE(bool, BOOL, bool) HANDLE_TYPE(int8, INT8, int8_t) HANDLE_TYPE(int16, INT16, int16_t) HANDLE_TYPE(int32, INT32, int32_t) HANDLE_TYPE(int64, INT64, int64_t) HANDLE_TYPE(uint8, UINT8, uint8_t) HANDLE_TYPE(uint16, UINT16, uint16_t) HANDLE_TYPE(uint32, UINT32, uint32_t) HANDLE_TYPE(uint64, UINT64, uint64_t) HANDLE_TYPE(float32, FLOAT32, float) HANDLE_TYPE(float64, FLOAT64, double) #undef HANDLE_TYPE case schema::Type::TEXT: builder.getPointerElement(bounded(index) * ELEMENTS).setBlob(value.as()); return; case schema::Type::DATA: builder.getPointerElement(bounded(index) * ELEMENTS).setBlob(value.as()); return; case schema::Type::LIST: { auto listValue = value.as(); KJ_REQUIRE(listValue.getSchema() == schema.getListElementType(), "Value type mismatch.") { return; } builder.getPointerElement(bounded(index) * ELEMENTS).setList(listValue.reader); return; } case schema::Type::STRUCT: { auto structValue = value.as(); KJ_REQUIRE(structValue.getSchema() == schema.getStructElementType(), "Value type mismatch.") { return; } builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(structValue.reader); return; } case schema::Type::ENUM: { uint16_t rawValue; if (value.getType() == DynamicValue::TEXT) { // Convert from text. rawValue = schema.getEnumElementType().getEnumerantByName(value.as()).getOrdinal(); } else { DynamicEnum enumValue = value.as(); KJ_REQUIRE(schema.getEnumElementType() == enumValue.getSchema(), "Type mismatch when using DynamicList::Builder::set().") { return; } rawValue = enumValue.getRaw(); } builder.setDataElement(bounded(index) * ELEMENTS, rawValue); return; } case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported.") { return; } case schema::Type::INTERFACE: { auto capValue = value.as(); KJ_REQUIRE(capValue.getSchema().extends(schema.getInterfaceElementType()), "Value type mismatch.") { return; } builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(capValue.hook)); return; } } KJ_FAIL_REQUIRE("can't set element of unknown type", (uint)schema.whichElementType()) { return; } } DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) { KJ_REQUIRE(index < this->size(), "List index out-of-bounds."); switch (schema.whichElementType()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: case schema::Type::STRUCT: case schema::Type::INTERFACE: KJ_FAIL_REQUIRE("Expected a list or blob."); return nullptr; case schema::Type::TEXT: return builder.getPointerElement(bounded(index) * ELEMENTS) .initBlob(bounded(size) * BYTES); case schema::Type::DATA: return builder.getPointerElement(bounded(index) * ELEMENTS) .initBlob(bounded(size) * BYTES); case schema::Type::LIST: { auto elementType = schema.getListElementType(); if (elementType.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(elementType, builder.getPointerElement(bounded(index) * ELEMENTS) .initStructList(bounded(size) * ELEMENTS, structSizeFromSchema(elementType.getStructElementType()))); } else { return DynamicList::Builder(elementType, builder.getPointerElement(bounded(index) * ELEMENTS) .initList(elementSizeFor(elementType.whichElementType()), bounded(size) * ELEMENTS)); } } case schema::Type::ANY_POINTER: { KJ_FAIL_ASSERT("List(AnyPointer) not supported."); return nullptr; } } return nullptr; } void DynamicList::Builder::adopt(uint index, Orphan&& orphan) { switch (schema.whichElementType()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: set(index, orphan.getReader()); return; case schema::Type::TEXT: KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); return; case schema::Type::DATA: KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); return; case schema::Type::LIST: { ListSchema elementType = schema.getListElementType(); KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == elementType, "Value type mismatch."); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); return; } case schema::Type::STRUCT: { auto elementType = schema.getStructElementType(); KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == elementType, "Value type mismatch."); builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom( orphan.builder.asStruct(structSizeFromSchema(elementType))); return; } case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported."); case schema::Type::INTERFACE: { auto elementType = schema.getInterfaceElementType(); KJ_REQUIRE(orphan.getType() == DynamicValue::CAPABILITY && orphan.interfaceSchema.extends(elementType), "Value type mismatch."); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(orphan.builder)); return; } } KJ_UNREACHABLE; } Orphan DynamicList::Builder::disown(uint index) { switch (schema.whichElementType()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: { auto result = Orphan(operator[](index), _::OrphanBuilder()); switch (elementSizeFor(schema.whichElementType())) { case ElementSize::VOID: break; case ElementSize::BIT: builder.setDataElement(bounded(index) * ELEMENTS, false); break; case ElementSize::BYTE: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; case ElementSize::TWO_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; case ElementSize::FOUR_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0); break; case ElementSize::EIGHT_BYTES: builder.setDataElement(bounded(index) * ELEMENTS, 0);break; case ElementSize::POINTER: case ElementSize::INLINE_COMPOSITE: KJ_UNREACHABLE; } return kj::mv(result); } case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::ANY_POINTER: case schema::Type::INTERFACE: { auto value = operator[](index); return Orphan(value, builder.getPointerElement(bounded(index) * ELEMENTS).disown()); } case schema::Type::STRUCT: { // We have to make a copy. Orphan result = Orphanage::getForMessageContaining(*this).newOrphan(schema.getStructElementType()); auto element = builder.getStructElement(bounded(index) * ELEMENTS); result.get().builder.transferContentFrom(element); element.clearAll(); return kj::mv(result); } } KJ_UNREACHABLE; } void DynamicList::Builder::copyFrom(std::initializer_list value) { KJ_REQUIRE(value.size() == size(), "DynamicList::copyFrom() argument had different size."); uint i = 0; for (auto element: value) { set(i++, element); } } DynamicList::Reader DynamicList::Builder::asReader() const { return DynamicList::Reader(schema, builder.asReader()); } // ======================================================================================= DynamicValue::Reader::Reader(ConstSchema constant): type(VOID) { auto type = constant.getType(); auto value = constant.getProto().getConst().getValue(); switch (type.which()) { case schema::Type::VOID: *this = capnp::VOID; break; case schema::Type::BOOL: *this = value.getBool(); break; case schema::Type::INT8: *this = value.getInt8(); break; case schema::Type::INT16: *this = value.getInt16(); break; case schema::Type::INT32: *this = value.getInt32(); break; case schema::Type::INT64: *this = value.getInt64(); break; case schema::Type::UINT8: *this = value.getUint8(); break; case schema::Type::UINT16: *this = value.getUint16(); break; case schema::Type::UINT32: *this = value.getUint32(); break; case schema::Type::UINT64: *this = value.getUint64(); break; case schema::Type::FLOAT32: *this = value.getFloat32(); break; case schema::Type::FLOAT64: *this = value.getFloat64(); break; case schema::Type::TEXT: *this = value.getText(); break; case schema::Type::DATA: *this = value.getData(); break; case schema::Type::ENUM: *this = DynamicEnum(type.asEnum(), value.getEnum()); break; case schema::Type::STRUCT: *this = value.getStruct().getAs(type.asStruct()); break; case schema::Type::LIST: *this = value.getList().getAs(type.asList()); break; case schema::Type::ANY_POINTER: *this = value.getAnyPointer(); break; case schema::Type::INTERFACE: KJ_FAIL_ASSERT("Constants can't have interface type."); } } #if __GNUC__ && !__clang__ && __GNUC__ >= 9 // In the copy constructors below, we use memcpy() to copy only after verifying that it is safe. // But GCC 9 doesn't know we've checked, and whines. I suppose GCC is probably right: our checks // probably don't technically make memcpy safe according to the standard. But it works in practice, // and if it ever stops working, the tests will catch it. #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif DynamicValue::Reader::Reader(const Reader& other) { switch (other.type) { case UNKNOWN: case VOID: case BOOL: case INT: case UINT: case FLOAT: case TEXT: case DATA: case LIST: case ENUM: case STRUCT: case ANY_POINTER: KJ_ASSERT_CAN_MEMCPY(Text::Reader); KJ_ASSERT_CAN_MEMCPY(Data::Reader); KJ_ASSERT_CAN_MEMCPY(DynamicList::Reader); KJ_ASSERT_CAN_MEMCPY(DynamicEnum); KJ_ASSERT_CAN_MEMCPY(DynamicStruct::Reader); KJ_ASSERT_CAN_MEMCPY(AnyPointer::Reader); break; case CAPABILITY: type = CAPABILITY; kj::ctor(capabilityValue, other.capabilityValue); return; } memcpy(this, &other, sizeof(*this)); } DynamicValue::Reader::Reader(Reader&& other) noexcept { switch (other.type) { case UNKNOWN: case VOID: case BOOL: case INT: case UINT: case FLOAT: case TEXT: case DATA: case LIST: case ENUM: case STRUCT: case ANY_POINTER: KJ_ASSERT_CAN_MEMCPY(Text::Reader); KJ_ASSERT_CAN_MEMCPY(Data::Reader); KJ_ASSERT_CAN_MEMCPY(DynamicList::Reader); KJ_ASSERT_CAN_MEMCPY(DynamicEnum); KJ_ASSERT_CAN_MEMCPY(DynamicStruct::Reader); KJ_ASSERT_CAN_MEMCPY(AnyPointer::Reader); break; case CAPABILITY: type = CAPABILITY; kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); return; } memcpy(this, &other, sizeof(*this)); } DynamicValue::Reader::~Reader() noexcept(false) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } } DynamicValue::Reader& DynamicValue::Reader::operator=(const Reader& other) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } kj::ctor(*this, other); return *this; } DynamicValue::Reader& DynamicValue::Reader::operator=(Reader&& other) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } kj::ctor(*this, kj::mv(other)); return *this; } DynamicValue::Builder::Builder(Builder& other) { switch (other.type) { case UNKNOWN: case VOID: case BOOL: case INT: case UINT: case FLOAT: case TEXT: case DATA: case LIST: case ENUM: case STRUCT: case ANY_POINTER: // Unfortunately canMemcpy() doesn't work on these types due to the use of // DisallowConstCopy, but __has_trivial_destructor should detect if any of these types // become non-trivial. static_assert(KJ_HAS_TRIVIAL_DESTRUCTOR(Text::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(Data::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicList::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicEnum) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicStruct::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(AnyPointer::Builder), "Assumptions here don't hold."); break; case CAPABILITY: type = CAPABILITY; kj::ctor(capabilityValue, other.capabilityValue); return; } memcpy(this, &other, sizeof(*this)); } DynamicValue::Builder::Builder(Builder&& other) noexcept { switch (other.type) { case UNKNOWN: case VOID: case BOOL: case INT: case UINT: case FLOAT: case TEXT: case DATA: case LIST: case ENUM: case STRUCT: case ANY_POINTER: // Unfortunately __has_trivial_copy doesn't work on these types due to the use of // DisallowConstCopy, but __has_trivial_destructor should detect if any of these types // become non-trivial. static_assert(KJ_HAS_TRIVIAL_DESTRUCTOR(Text::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(Data::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicList::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicEnum) && KJ_HAS_TRIVIAL_DESTRUCTOR(DynamicStruct::Builder) && KJ_HAS_TRIVIAL_DESTRUCTOR(AnyPointer::Builder), "Assumptions here don't hold."); break; case CAPABILITY: type = CAPABILITY; kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); return; } memcpy(this, &other, sizeof(*this)); } DynamicValue::Builder::~Builder() noexcept(false) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } } DynamicValue::Builder& DynamicValue::Builder::operator=(Builder& other) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } kj::ctor(*this, other); return *this; } DynamicValue::Builder& DynamicValue::Builder::operator=(Builder&& other) { if (type == CAPABILITY) { kj::dtor(capabilityValue); } kj::ctor(*this, kj::mv(other)); return *this; } DynamicValue::Reader DynamicValue::Builder::asReader() const { switch (type) { case UNKNOWN: return Reader(); case VOID: return Reader(voidValue); case BOOL: return Reader(boolValue); case INT: return Reader(intValue); case UINT: return Reader(uintValue); case FLOAT: return Reader(floatValue); case TEXT: return Reader(textValue.asReader()); case DATA: return Reader(dataValue.asReader()); case LIST: return Reader(listValue.asReader()); case ENUM: return Reader(enumValue); case STRUCT: return Reader(structValue.asReader()); case CAPABILITY: return Reader(capabilityValue); case ANY_POINTER: return Reader(anyPointerValue.asReader()); } KJ_FAIL_ASSERT("Missing switch case."); return Reader(); } DynamicValue::Pipeline::Pipeline(Pipeline&& other) noexcept: type(other.type) { switch (type) { case UNKNOWN: break; case STRUCT: kj::ctor(structValue, kj::mv(other.structValue)); break; case CAPABILITY: kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); break; default: KJ_LOG(ERROR, "Unexpected pipeline type.", (uint)type); type = UNKNOWN; break; } } DynamicValue::Pipeline& DynamicValue::Pipeline::operator=(Pipeline&& other) { kj::dtor(*this); kj::ctor(*this, kj::mv(other)); return *this; } DynamicValue::Pipeline::~Pipeline() noexcept(false) { switch (type) { case UNKNOWN: break; case STRUCT: kj::dtor(structValue); break; case CAPABILITY: kj::dtor(capabilityValue); break; default: KJ_FAIL_ASSERT("Unexpected pipeline type.", (uint)type) { type = UNKNOWN; break; } break; } } namespace { template T signedToUnsigned(long long value) { KJ_REQUIRE(value >= 0 && T(value) == value, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return value; } template <> uint64_t signedToUnsigned(long long value) { KJ_REQUIRE(value >= 0, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return value; } template T unsignedToSigned(unsigned long long value) { KJ_REQUIRE(T(value) >= 0 && (unsigned long long)T(value) == value, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return value; } template <> int64_t unsignedToSigned(unsigned long long value) { KJ_REQUIRE(int64_t(value) >= 0, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return value; } template T checkRoundTrip(U value) { T result = value; KJ_REQUIRE(U(result) == value, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return result; } template T checkRoundTripFromFloat(U value) { // When `U` is `float` or `double`, we have to use a different approach, because casting an // out-of-range float to an integer is, surprisingly, UB. constexpr T MIN = kj::minValue; constexpr T MAX = kj::maxValue; KJ_REQUIRE(value >= U(MIN), "Value out-of-range for requested type.", value) { return MIN; } KJ_REQUIRE(value <= U(MAX), "Value out-of-range for requested type.", value) { return MAX; } T result = value; KJ_REQUIRE(U(result) == value, "Value out-of-range for requested type.", value) { // Use it anyway. break; } return result; } } // namespace #define HANDLE_NUMERIC_TYPE(typeName, ifInt, ifUint, ifFloat) \ typeName DynamicValue::Reader::AsImpl::apply(const Reader& reader) { \ switch (reader.type) { \ case INT: \ return ifInt(reader.intValue); \ case UINT: \ return ifUint(reader.uintValue); \ case FLOAT: \ return ifFloat(reader.floatValue); \ default: \ KJ_FAIL_REQUIRE("Value type mismatch.") { \ return 0; \ } \ } \ } \ typeName DynamicValue::Builder::AsImpl::apply(Builder& builder) { \ switch (builder.type) { \ case INT: \ return ifInt(builder.intValue); \ case UINT: \ return ifUint(builder.uintValue); \ case FLOAT: \ return ifFloat(builder.floatValue); \ default: \ KJ_FAIL_REQUIRE("Value type mismatch.") { \ return 0; \ } \ } \ } HANDLE_NUMERIC_TYPE(int8_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(int16_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(int32_t, checkRoundTrip, unsignedToSigned, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(int64_t, kj::implicitCast, unsignedToSigned, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(uint8_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(uint16_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(uint32_t, signedToUnsigned, checkRoundTrip, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, kj::implicitCast, checkRoundTripFromFloat) HANDLE_NUMERIC_TYPE(float, kj::implicitCast, kj::implicitCast, kj::implicitCast) HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast) #undef HANDLE_NUMERIC_TYPE #define HANDLE_TYPE(name, discrim, typeName) \ ReaderFor DynamicValue::Reader::AsImpl::apply(const Reader& reader) { \ KJ_REQUIRE(reader.type == discrim, "Value type mismatch.") { \ return ReaderFor(); \ } \ return reader.name##Value; \ } \ BuilderFor DynamicValue::Builder::AsImpl::apply(Builder& builder) { \ KJ_REQUIRE(builder.type == discrim, "Value type mismatch."); \ return builder.name##Value; \ } //HANDLE_TYPE(void, VOID, Void) HANDLE_TYPE(bool, BOOL, bool) HANDLE_TYPE(text, TEXT, Text) HANDLE_TYPE(list, LIST, DynamicList) HANDLE_TYPE(struct, STRUCT, DynamicStruct) HANDLE_TYPE(enum, ENUM, DynamicEnum) HANDLE_TYPE(anyPointer, ANY_POINTER, AnyPointer) #undef HANDLE_TYPE PipelineFor DynamicValue::Pipeline::AsImpl::apply( Pipeline& pipeline) { KJ_REQUIRE(pipeline.type == STRUCT, "Pipeline type mismatch."); return kj::mv(pipeline.structValue); } ReaderFor DynamicValue::Reader::AsImpl::apply( const Reader& reader) { KJ_REQUIRE(reader.type == CAPABILITY, "Value type mismatch.") { return DynamicCapability::Client(); } return reader.capabilityValue; } BuilderFor DynamicValue::Builder::AsImpl::apply( Builder& builder) { KJ_REQUIRE(builder.type == CAPABILITY, "Value type mismatch.") { return DynamicCapability::Client(); } return builder.capabilityValue; } PipelineFor DynamicValue::Pipeline::AsImpl::apply( Pipeline& pipeline) { KJ_REQUIRE(pipeline.type == CAPABILITY, "Pipeline type mismatch.") { return DynamicCapability::Client(); } return kj::mv(pipeline.capabilityValue); } Data::Reader DynamicValue::Reader::AsImpl::apply(const Reader& reader) { if (reader.type == TEXT) { // Coerce text to data. return reader.textValue.asBytes(); } KJ_REQUIRE(reader.type == DATA, "Value type mismatch.") { return Data::Reader(); } return reader.dataValue; } Data::Builder DynamicValue::Builder::AsImpl::apply(Builder& builder) { if (builder.type == TEXT) { // Coerce text to data. return builder.textValue.asBytes(); } KJ_REQUIRE(builder.type == DATA, "Value type mismatch.") { return BuilderFor(); } return builder.dataValue; } // As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7. Void DynamicValue::Reader::AsImpl::apply(const Reader& reader) { KJ_REQUIRE(reader.type == VOID, "Value type mismatch.") { return Void(); } return reader.voidValue; } Void DynamicValue::Builder::AsImpl::apply(Builder& builder) { KJ_REQUIRE(builder.type == VOID, "Value type mismatch.") { return Void(); } return builder.voidValue; } // ======================================================================================= namespace _ { // private DynamicStruct::Reader PointerHelpers::getDynamic( PointerReader reader, StructSchema schema) { KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), "Cannot form pointer to group type."); return DynamicStruct::Reader(schema, reader.getStruct(nullptr)); } DynamicStruct::Builder PointerHelpers::getDynamic( PointerBuilder builder, StructSchema schema) { KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), "Cannot form pointer to group type."); return DynamicStruct::Builder(schema, builder.getStruct( structSizeFromSchema(schema), nullptr)); } void PointerHelpers::set( PointerBuilder builder, const DynamicStruct::Reader& value) { KJ_REQUIRE(!value.schema.getProto().getStruct().getIsGroup(), "Cannot form pointer to group type."); builder.setStruct(value.reader); } DynamicStruct::Builder PointerHelpers::init( PointerBuilder builder, StructSchema schema) { KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), "Cannot form pointer to group type."); return DynamicStruct::Builder(schema, builder.initStruct(structSizeFromSchema(schema))); } DynamicList::Reader PointerHelpers::getDynamic( PointerReader reader, ListSchema schema) { return DynamicList::Reader(schema, reader.getList(elementSizeFor(schema.whichElementType()), nullptr)); } DynamicList::Builder PointerHelpers::getDynamic( PointerBuilder builder, ListSchema schema) { if (schema.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(schema, builder.getStructList( structSizeFromSchema(schema.getStructElementType()), nullptr)); } else { return DynamicList::Builder(schema, builder.getList(elementSizeFor(schema.whichElementType()), nullptr)); } } void PointerHelpers::set( PointerBuilder builder, const DynamicList::Reader& value) { builder.setList(value.reader); } DynamicList::Builder PointerHelpers::init( PointerBuilder builder, ListSchema schema, uint size) { if (schema.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(schema, builder.initStructList(bounded(size) * ELEMENTS, structSizeFromSchema(schema.getStructElementType()))); } else { return DynamicList::Builder(schema, builder.initList(elementSizeFor(schema.whichElementType()), bounded(size) * ELEMENTS)); } } DynamicCapability::Client PointerHelpers::getDynamic( PointerReader reader, InterfaceSchema schema) { return DynamicCapability::Client(schema, reader.getCapability()); } DynamicCapability::Client PointerHelpers::getDynamic( PointerBuilder builder, InterfaceSchema schema) { return DynamicCapability::Client(schema, builder.getCapability()); } void PointerHelpers::set( PointerBuilder builder, DynamicCapability::Client& value) { builder.setCapability(value.hook->addRef()); } void PointerHelpers::set( PointerBuilder builder, DynamicCapability::Client&& value) { builder.setCapability(kj::mv(value.hook)); } } // namespace _ (private) template <> void AnyPointer::Builder::adopt(Orphan&& orphan) { switch (orphan.getType()) { case DynamicValue::UNKNOWN: case DynamicValue::VOID: case DynamicValue::BOOL: case DynamicValue::INT: case DynamicValue::UINT: case DynamicValue::FLOAT: case DynamicValue::ENUM: KJ_FAIL_REQUIRE("AnyPointer cannot adopt primitive (non-object) value."); case DynamicValue::STRUCT: case DynamicValue::LIST: case DynamicValue::TEXT: case DynamicValue::DATA: case DynamicValue::CAPABILITY: case DynamicValue::ANY_POINTER: builder.adopt(kj::mv(orphan.builder)); break; } } DynamicStruct::Reader::Reader(StructSchema schema, const _::OrphanBuilder& orphan) : schema(schema), reader(orphan.asStructReader(structSizeFromSchema(schema))) {} DynamicStruct::Builder::Builder(StructSchema schema, _::OrphanBuilder& orphan) : schema(schema), builder(orphan.asStruct(structSizeFromSchema(schema))) {} DynamicList::Reader::Reader(ListSchema schema, const _::OrphanBuilder& orphan) : schema(schema), reader(orphan.asListReader(elementSizeFor(schema.whichElementType()))) {} DynamicList::Builder::Builder(ListSchema schema, _::OrphanBuilder& orphan) : schema(schema), builder(schema.whichElementType() == schema::Type::STRUCT ? orphan.asStructList(structSizeFromSchema(schema.getStructElementType())) : orphan.asList(elementSizeFor(schema.whichElementType()))) {} // ------------------------------------------------------------------- Orphan Orphanage::newOrphan(StructSchema schema) const { return Orphan( schema, _::OrphanBuilder::initStruct(arena, capTable, structSizeFromSchema(schema))); } Orphan Orphanage::newOrphan(ListSchema schema, uint size) const { if (schema.whichElementType() == schema::Type::STRUCT) { return Orphan(schema, _::OrphanBuilder::initStructList( arena, capTable, bounded(size) * ELEMENTS, structSizeFromSchema(schema.getStructElementType()))); } else { return Orphan(schema, _::OrphanBuilder::initList( arena, capTable, bounded(size) * ELEMENTS, elementSizeFor(schema.whichElementType()))); } } DynamicStruct::Builder Orphan::get() { return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema))); } DynamicStruct::Reader Orphan::getReader() const { return DynamicStruct::Reader(schema, builder.asStructReader(structSizeFromSchema(schema))); } DynamicList::Builder Orphan::get() { if (schema.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder( schema, builder.asStructList(structSizeFromSchema(schema.getStructElementType()))); } else { return DynamicList::Builder( schema, builder.asList(elementSizeFor(schema.whichElementType()))); } } DynamicList::Reader Orphan::getReader() const { return DynamicList::Reader( schema, builder.asListReader(elementSizeFor(schema.whichElementType()))); } DynamicCapability::Client Orphan::get() { return DynamicCapability::Client(schema, builder.asCapability()); } DynamicCapability::Client Orphan::getReader() const { return DynamicCapability::Client(schema, builder.asCapability()); } Orphan::Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder) : type(value.getType()), builder(kj::mv(builder)) { switch (type) { case DynamicValue::UNKNOWN: break; case DynamicValue::VOID: voidValue = value.voidValue; break; case DynamicValue::BOOL: boolValue = value.boolValue; break; case DynamicValue::INT: intValue = value.intValue; break; case DynamicValue::UINT: uintValue = value.uintValue; break; case DynamicValue::FLOAT: floatValue = value.floatValue; break; case DynamicValue::ENUM: enumValue = value.enumValue; break; case DynamicValue::TEXT: break; case DynamicValue::DATA: break; case DynamicValue::LIST: listSchema = value.listValue.getSchema(); break; case DynamicValue::STRUCT: structSchema = value.structValue.getSchema(); break; case DynamicValue::CAPABILITY: interfaceSchema = value.capabilityValue.getSchema(); break; case DynamicValue::ANY_POINTER: break; } } DynamicValue::Builder Orphan::get() { switch (type) { case DynamicValue::UNKNOWN: return nullptr; case DynamicValue::VOID: return voidValue; case DynamicValue::BOOL: return boolValue; case DynamicValue::INT: return intValue; case DynamicValue::UINT: return uintValue; case DynamicValue::FLOAT: return floatValue; case DynamicValue::ENUM: return enumValue; case DynamicValue::TEXT: return builder.asText(); case DynamicValue::DATA: return builder.asData(); case DynamicValue::LIST: if (listSchema.whichElementType() == schema::Type::STRUCT) { return DynamicList::Builder(listSchema, builder.asStructList(structSizeFromSchema(listSchema.getStructElementType()))); } else { return DynamicList::Builder(listSchema, builder.asList(elementSizeFor(listSchema.whichElementType()))); } case DynamicValue::STRUCT: return DynamicStruct::Builder(structSchema, builder.asStruct(structSizeFromSchema(structSchema))); case DynamicValue::CAPABILITY: return DynamicCapability::Client(interfaceSchema, builder.asCapability()); case DynamicValue::ANY_POINTER: KJ_FAIL_REQUIRE("Can't get() an AnyPointer orphan; there is no underlying pointer to " "wrap in an AnyPointer::Builder."); } KJ_UNREACHABLE; } DynamicValue::Reader Orphan::getReader() const { switch (type) { case DynamicValue::UNKNOWN: return nullptr; case DynamicValue::VOID: return voidValue; case DynamicValue::BOOL: return boolValue; case DynamicValue::INT: return intValue; case DynamicValue::UINT: return uintValue; case DynamicValue::FLOAT: return floatValue; case DynamicValue::ENUM: return enumValue; case DynamicValue::TEXT: return builder.asTextReader(); case DynamicValue::DATA: return builder.asDataReader(); case DynamicValue::LIST: return DynamicList::Reader(listSchema, builder.asListReader(elementSizeFor(listSchema.whichElementType()))); case DynamicValue::STRUCT: return DynamicStruct::Reader(structSchema, builder.asStructReader(structSizeFromSchema(structSchema))); case DynamicValue::CAPABILITY: return DynamicCapability::Client(interfaceSchema, builder.asCapability()); case DynamicValue::ANY_POINTER: KJ_FAIL_ASSERT("Can't get() an AnyPointer orphan; there is no underlying pointer to " "wrap in an AnyPointer::Builder."); } KJ_UNREACHABLE; } template <> Orphan Orphan::releaseAs() { KJ_REQUIRE(type == DynamicValue::ANY_POINTER, "Value type mismatch."); type = DynamicValue::UNKNOWN; return Orphan(kj::mv(builder)); } template <> Orphan Orphan::releaseAs() { KJ_REQUIRE(type == DynamicValue::STRUCT, "Value type mismatch."); type = DynamicValue::UNKNOWN; return Orphan(structSchema, kj::mv(builder)); } template <> Orphan Orphan::releaseAs() { KJ_REQUIRE(type == DynamicValue::LIST, "Value type mismatch."); type = DynamicValue::UNKNOWN; return Orphan(listSchema, kj::mv(builder)); } template <> Orphan Orphanage::newOrphanCopy( DynamicValue::Reader copyFrom) const { switch (copyFrom.getType()) { case DynamicValue::UNKNOWN: return nullptr; case DynamicValue::VOID: return copyFrom.voidValue; case DynamicValue::BOOL: return copyFrom.boolValue; case DynamicValue::INT: return copyFrom.intValue; case DynamicValue::UINT: return copyFrom.uintValue; case DynamicValue::FLOAT: return copyFrom.floatValue; case DynamicValue::ENUM: return copyFrom.enumValue; case DynamicValue::TEXT: return newOrphanCopy(copyFrom.textValue); case DynamicValue::DATA: return newOrphanCopy(copyFrom.dataValue); case DynamicValue::LIST: return newOrphanCopy(copyFrom.listValue); case DynamicValue::STRUCT: return newOrphanCopy(copyFrom.structValue); case DynamicValue::CAPABILITY: return newOrphanCopy(copyFrom.capabilityValue); case DynamicValue::ANY_POINTER: return newOrphanCopy(copyFrom.anyPointerValue); } KJ_UNREACHABLE; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/blob-test.c++0000644000175000017500000001074314527152321021026 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "blob.h" #include #include #include #include "test-util.h" // TODO(test): This test is outdated -- it predates the retrofit of Text and Data on top of // kj::ArrayPtr/kj::StringPtr. Clean it up. namespace capnp { namespace { TEST(Blob, Text) { std::string str = "foo"; Text::Reader text = str.c_str(); EXPECT_EQ("foo", text); EXPECT_STREQ("foo", text.cStr()); EXPECT_STREQ("foo", text.begin()); EXPECT_EQ(3u, text.size()); Text::Reader text2 = "bar"; EXPECT_EQ("bar", text2); char c[4] = "baz"; Text::Reader text3(c); EXPECT_EQ("baz", text3); Text::Builder builder(c, 3); EXPECT_EQ("baz", builder); EXPECT_EQ(kj::arrayPtr("az", 2), builder.slice(1, 3)); } Data::Reader dataLit(const char* str) { return Data::Reader(reinterpret_cast(str), strlen(str)); } TEST(Blob, Data) { Data::Reader data = dataLit("foo"); EXPECT_EQ(dataLit("foo"), data); EXPECT_EQ(3u, data.size()); Data::Reader data2 = dataLit("bar"); EXPECT_EQ(dataLit("bar"), data2); byte c[4] = "baz"; Data::Reader data3(c, 3); EXPECT_EQ(dataLit("baz"), data3); Data::Builder builder(c, 3); EXPECT_EQ(dataLit("baz"), builder); EXPECT_EQ(dataLit("az"), builder.slice(1, 3)); } TEST(Blob, Compare) { EXPECT_TRUE (Text::Reader("foo") == Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foo") != Text::Reader("foo")); EXPECT_TRUE (Text::Reader("foo") <= Text::Reader("foo")); EXPECT_TRUE (Text::Reader("foo") >= Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foo") < Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foo") > Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foo") == Text::Reader("bar")); EXPECT_TRUE (Text::Reader("foo") != Text::Reader("bar")); EXPECT_FALSE(Text::Reader("foo") <= Text::Reader("bar")); EXPECT_TRUE (Text::Reader("foo") >= Text::Reader("bar")); EXPECT_FALSE(Text::Reader("foo") < Text::Reader("bar")); EXPECT_TRUE (Text::Reader("foo") > Text::Reader("bar")); EXPECT_FALSE(Text::Reader("bar") == Text::Reader("foo")); EXPECT_TRUE (Text::Reader("bar") != Text::Reader("foo")); EXPECT_TRUE (Text::Reader("bar") <= Text::Reader("foo")); EXPECT_FALSE(Text::Reader("bar") >= Text::Reader("foo")); EXPECT_TRUE (Text::Reader("bar") < Text::Reader("foo")); EXPECT_FALSE(Text::Reader("bar") > Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foobar") == Text::Reader("foo")); EXPECT_TRUE (Text::Reader("foobar") != Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foobar") <= Text::Reader("foo")); EXPECT_TRUE (Text::Reader("foobar") >= Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foobar") < Text::Reader("foo")); EXPECT_TRUE (Text::Reader("foobar") > Text::Reader("foo")); EXPECT_FALSE(Text::Reader("foo") == Text::Reader("foobar")); EXPECT_TRUE (Text::Reader("foo") != Text::Reader("foobar")); EXPECT_TRUE (Text::Reader("foo") <= Text::Reader("foobar")); EXPECT_FALSE(Text::Reader("foo") >= Text::Reader("foobar")); EXPECT_TRUE (Text::Reader("foo") < Text::Reader("foobar")); EXPECT_FALSE(Text::Reader("foo") > Text::Reader("foobar")); } #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP TEST(Blob, StlInterop) { std::string foo = "foo"; Text::Reader reader = foo; EXPECT_EQ("foo", reader); std::string bar = reader; EXPECT_EQ("foo", bar); } #endif } // namespace } // namespace capnp capnproto-c++-1.1.0/src/capnp/orphan-test.c++0000644000175000017500000015061214527152321021377 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "message.h" #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { TEST(Orphans, Structs) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root.initStructField()); EXPECT_TRUE(root.hasStructField()); Orphan orphan = root.disownStructField(); EXPECT_FALSE(orphan == nullptr); checkTestMessage(orphan.getReader()); checkTestMessage(orphan.get()); EXPECT_FALSE(root.hasStructField()); root.adoptStructField(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasStructField()); checkTestMessage(root.asReader().getStructField()); } TEST(Orphans, EmptyStruct) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto anyPointer = root.getAnyPointerField(); EXPECT_TRUE(anyPointer.isNull()); auto orphan = builder.getOrphanage().newOrphan(); anyPointer.adopt(kj::mv(orphan)); EXPECT_EQ(0, anyPointer.targetSize().wordCount); EXPECT_FALSE(anyPointer.isNull()); } TEST(Orphans, EmptyStructOverwrite) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto anyPointer = root.getAnyPointerField(); EXPECT_TRUE(anyPointer.isNull()); anyPointer.initAs(); auto orphan = builder.getOrphanage().newOrphan(); anyPointer.adopt(kj::mv(orphan)); EXPECT_EQ(0, anyPointer.targetSize().wordCount); EXPECT_FALSE(anyPointer.isNull()); } TEST(Orphans, AdoptNullStruct) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto anyPointer = root.getAnyPointerField(); EXPECT_TRUE(anyPointer.isNull()); anyPointer.initAs(); anyPointer.adopt(Orphan()); EXPECT_EQ(0, anyPointer.targetSize().wordCount); EXPECT_TRUE(anyPointer.isNull()); } TEST(Orphans, Lists) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.setUInt32List({12, 34, 56}); EXPECT_TRUE(root.hasUInt32List()); Orphan> orphan = root.disownUInt32List(); EXPECT_FALSE(orphan == nullptr); checkList(orphan.getReader(), {12u, 34u, 56u}); checkList(orphan.get(), {12u, 34u, 56u}); EXPECT_FALSE(root.hasUInt32List()); root.adoptUInt32List(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasUInt32List()); checkList(root.asReader().getUInt32List(), {12u, 34u, 56u}); } TEST(Orphans, StructLists) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto list = root.initStructList(2); list[0].setTextField("foo"); list[1].setTextField("bar"); EXPECT_TRUE(root.hasStructList()); Orphan> orphan = root.disownStructList(); EXPECT_FALSE(orphan == nullptr); ASSERT_EQ(2u, orphan.getReader().size()); EXPECT_EQ("foo", orphan.getReader()[0].getTextField()); EXPECT_EQ("bar", orphan.getReader()[1].getTextField()); ASSERT_EQ(2u, orphan.get().size()); EXPECT_EQ("foo", orphan.get()[0].getTextField()); EXPECT_EQ("bar", orphan.get()[1].getTextField()); EXPECT_FALSE(root.hasStructList()); root.adoptStructList(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasStructList()); ASSERT_EQ(2u, root.asReader().getStructList().size()); EXPECT_EQ("foo", root.asReader().getStructList()[0].getTextField()); EXPECT_EQ("bar", root.asReader().getStructList()[1].getTextField()); } TEST(Orphans, Text) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.setTextField("foo"); EXPECT_TRUE(root.hasTextField()); Orphan orphan = root.disownTextField(); EXPECT_FALSE(orphan == nullptr); EXPECT_EQ("foo", orphan.getReader()); EXPECT_EQ("foo", orphan.get()); EXPECT_FALSE(root.hasTextField()); root.adoptTextField(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasTextField()); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, Data) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.setDataField(data("foo")); EXPECT_TRUE(root.hasDataField()); Orphan orphan = root.disownDataField(); EXPECT_FALSE(orphan == nullptr); EXPECT_EQ(data("foo"), orphan.getReader()); EXPECT_EQ(data("foo"), orphan.get()); EXPECT_FALSE(root.hasDataField()); root.adoptDataField(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasDataField()); EXPECT_EQ(data("foo"), root.getDataField()); } TEST(Orphans, NoCrossMessageTransfers) { MallocMessageBuilder builder1; MallocMessageBuilder builder2; auto root1 = builder1.initRoot(); auto root2 = builder2.initRoot(); initTestMessage(root1.initStructField()); EXPECT_ANY_THROW(root2.adoptStructField(root1.disownStructField())); } TEST(Orphans, OrphanageStruct) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphan(); initTestMessage(orphan.get()); checkTestMessage(orphan.getReader()); auto root = builder.initRoot(); root.adoptStructField(kj::mv(orphan)); } TEST(Orphans, OrphanageList) { MallocMessageBuilder builder; Orphan> orphan = builder.getOrphanage().newOrphan>(2); orphan.get().set(0, 123); orphan.get().set(1, 456); List::Reader reader = orphan.getReader(); ASSERT_EQ(2u, reader.size()); EXPECT_EQ(123u, reader[0]); EXPECT_EQ(456u, reader[1]); auto root = builder.initRoot(); root.adoptUInt32List(kj::mv(orphan)); } TEST(Orphans, OrphanageText) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphan(8); ASSERT_EQ(8u, orphan.get().size()); memcpy(orphan.get().begin(), "12345678", 8); auto root = builder.initRoot(); root.adoptTextField(kj::mv(orphan)); EXPECT_EQ("12345678", root.getTextField()); } TEST(Orphans, OrphanageData) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphan(2); ASSERT_EQ(2u, orphan.get().size()); orphan.get()[0] = 123; orphan.get()[1] = 45; auto root = builder.initRoot(); root.adoptDataField(kj::mv(orphan)); ASSERT_EQ(2u, root.getDataField().size()); EXPECT_EQ(123u, root.getDataField()[0]); EXPECT_EQ(45u, root.getDataField()[1]); } TEST(Orphans, OrphanageStructCopy) { MallocMessageBuilder builder1; MallocMessageBuilder builder2; auto root1 = builder1.initRoot(); initTestMessage(root1); Orphan orphan = builder2.getOrphanage().newOrphanCopy(root1.asReader()); checkTestMessage(orphan.getReader()); auto root2 = builder2.initRoot(); root2.adoptStructField(kj::mv(orphan)); } TEST(Orphans, OrphanageListCopy) { MallocMessageBuilder builder1; MallocMessageBuilder builder2; auto root1 = builder1.initRoot(); root1.setUInt32List({12, 34, 56}); Orphan> orphan = builder2.getOrphanage().newOrphanCopy( root1.asReader().getUInt32List()); checkList(orphan.getReader(), {12u, 34u, 56u}); auto root2 = builder2.initRoot(); root2.adoptUInt32List(kj::mv(orphan)); } TEST(Orphans, OrphanageTextCopy) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphanCopy(Text::Reader("foobarba")); EXPECT_EQ("foobarba", orphan.getReader()); auto root = builder.initRoot(); root.adoptTextField(kj::mv(orphan)); } TEST(Orphans, OrphanageDataCopy) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphanCopy(data("foo")); EXPECT_EQ(data("foo"), orphan.getReader()); auto root = builder.initRoot(); root.adoptDataField(kj::mv(orphan)); } TEST(Orphans, ZeroOut) { MallocMessageBuilder builder; TestAllTypes::Reader orphanReader; { Orphan orphan = builder.getOrphanage().newOrphan(); orphanReader = orphan.getReader(); initTestMessage(orphan.get()); checkTestMessage(orphan.getReader()); } // Once the Orphan destructor is called, the message should be zero'd out. checkTestMessageAllZero(orphanReader); } TEST(Orphans, StructAnyPointer) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root.getAnyPointerField().initAs()); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(); EXPECT_FALSE(orphan == nullptr); checkTestMessage(orphan.getReader()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasAnyPointerField()); checkTestMessage(root.asReader().getAnyPointerField().getAs()); } TEST(Orphans, ListAnyPointer) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({12, 34, 56}); EXPECT_TRUE(root.hasAnyPointerField()); Orphan> orphan = root.getAnyPointerField().disownAs>(); EXPECT_FALSE(orphan == nullptr); checkList(orphan.getReader(), {12u, 34u, 56u}); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasAnyPointerField()); checkList(root.asReader().getAnyPointerField().getAs>(), {12u, 34u, 56u}); } #if !CAPNP_LITE TEST(Orphans, DynamicStruct) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root.getAnyPointerField().initAs()); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(Schema::from()); EXPECT_FALSE(orphan == nullptr); EXPECT_TRUE(orphan.get().getSchema() == Schema::from()); checkDynamicTestMessage(orphan.getReader()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasAnyPointerField()); checkTestMessage(root.asReader().getAnyPointerField().getAs()); Orphan orphan2 = root.getAnyPointerField().disownAs(); EXPECT_FALSE(orphan2 == nullptr); EXPECT_TRUE(orphan2.get().getSchema() == Schema::from()); checkDynamicTestMessage(orphan2.getReader()); } TEST(Orphans, DynamicList) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({12, 34, 56}); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(Schema::from>()); EXPECT_FALSE(orphan == nullptr); checkList(orphan.getReader(), {12, 34, 56}); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasAnyPointerField()); checkList(root.asReader().getAnyPointerField().getAs>(), {12u, 34u, 56u}); Orphan orphan2 = root.getAnyPointerField().disownAs>(); EXPECT_FALSE(orphan2 == nullptr); checkList(orphan2.getReader(), {12, 34, 56}); } TEST(Orphans, DynamicStructList) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto list = root.getAnyPointerField().initAs>(2); list[0].setTextField("foo"); list[1].setTextField("bar"); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(Schema::from>()); EXPECT_FALSE(orphan == nullptr); ASSERT_EQ(2u, orphan.get().size()); EXPECT_EQ("foo", orphan.get()[0].as().getTextField()); EXPECT_EQ("bar", orphan.get()[1].as().getTextField()); EXPECT_FALSE(root.hasAnyPointerField()); root.getAnyPointerField().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); EXPECT_TRUE(root.hasAnyPointerField()); ASSERT_EQ(2u, root.asReader().getAnyPointerField().getAs>().size()); EXPECT_EQ("foo", root.asReader().getAnyPointerField() .getAs>()[0].getTextField()); EXPECT_EQ("bar", root.asReader().getAnyPointerField() .getAs>()[1].getTextField()); } TEST(Orphans, OrphanageDynamicStruct) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphan(Schema::from()); initDynamicTestMessage(orphan.get()); checkDynamicTestMessage(orphan.getReader()); auto root = builder.initRoot(); root.getAnyPointerField().adopt(kj::mv(orphan)); checkTestMessage(root.asReader().getAnyPointerField().getAs()); } TEST(Orphans, OrphanageDynamicList) { MallocMessageBuilder builder; Orphan orphan = builder.getOrphanage().newOrphan(Schema::from>(), 2); orphan.get().set(0, 123); orphan.get().set(1, 456); checkList(orphan.getReader(), {123, 456}); auto root = builder.initRoot(); root.getAnyPointerField().adopt(kj::mv(orphan)); checkList(root.getAnyPointerField().getAs>(), {123u, 456u}); } TEST(Orphans, OrphanageDynamicStructCopy) { MallocMessageBuilder builder1; MallocMessageBuilder builder2; auto root1 = builder1.initRoot(); initTestMessage(root1.getAnyPointerField().initAs()); Orphan orphan = builder2.getOrphanage().newOrphanCopy( root1.asReader().getAnyPointerField().getAs(Schema::from())); checkDynamicTestMessage(orphan.getReader()); auto root2 = builder2.initRoot(); root2.getAnyPointerField().adopt(kj::mv(orphan)); checkTestMessage(root2.asReader().getAnyPointerField().getAs()); } TEST(Orphans, OrphanageDynamicListCopy) { MallocMessageBuilder builder1; MallocMessageBuilder builder2; auto root1 = builder1.initRoot(); root1.getAnyPointerField().setAs>({12, 34, 56}); Orphan orphan = builder2.getOrphanage().newOrphanCopy( root1.asReader().getAnyPointerField().getAs(Schema::from>())); checkList(orphan.getReader(), {12, 34, 56}); auto root2 = builder2.initRoot(); root2.getAnyPointerField().adopt(kj::mv(orphan)); checkList(root2.getAnyPointerField().getAs>(), {12u, 34u, 56u}); } TEST(Orphans, DynamicStructAs) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root.getAnyPointerField().initAs()); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(Schema::from()); EXPECT_EQ(DynamicValue::STRUCT, orphan.getType()); checkTestMessage(orphan.getReader().as()); checkTestMessage(orphan.get().as()); { Orphan structOrphan = orphan.releaseAs(); EXPECT_EQ(DynamicValue::UNKNOWN, orphan.getType()); EXPECT_FALSE(structOrphan == nullptr); checkDynamicTestMessage(structOrphan.getReader()); checkDynamicTestMessage(structOrphan.get()); checkTestMessage(structOrphan.getReader().as()); checkTestMessage(structOrphan.get().as()); { Orphan typedOrphan = structOrphan.releaseAs(); EXPECT_TRUE(structOrphan == nullptr); EXPECT_FALSE(typedOrphan == nullptr); checkTestMessage(typedOrphan.getReader()); checkTestMessage(typedOrphan.get()); orphan = kj::mv(typedOrphan); EXPECT_EQ(DynamicValue::STRUCT, orphan.getType()); EXPECT_TRUE(typedOrphan == nullptr); } } { Orphan typedOrphan = orphan.releaseAs(); checkTestMessage(typedOrphan.getReader()); checkTestMessage(typedOrphan.get()); } } TEST(Orphans, DynamicListAs) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getAnyPointerField().setAs>({12, 34, 56}); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disownAs(Schema::from>()); EXPECT_EQ(DynamicValue::LIST, orphan.getType()); checkList(orphan.getReader().as>(), {12, 34, 56}); checkList(orphan.get().as>(), {12, 34, 56}); { Orphan listOrphan = orphan.releaseAs(); EXPECT_EQ(DynamicValue::UNKNOWN, orphan.getType()); EXPECT_FALSE(listOrphan == nullptr); checkList(listOrphan.getReader(), {12, 34, 56}); checkList(listOrphan.get(), {12, 34, 56}); checkList(listOrphan.getReader().as>(), {12, 34, 56}); checkList(listOrphan.get().as>(), {12, 34, 56}); { Orphan> typedOrphan = listOrphan.releaseAs>(); EXPECT_TRUE(listOrphan == nullptr); EXPECT_FALSE(typedOrphan == nullptr); checkList(typedOrphan.getReader(), {12, 34, 56}); checkList(typedOrphan.get(), {12, 34, 56}); orphan = kj::mv(typedOrphan); EXPECT_EQ(DynamicValue::LIST, orphan.getType()); EXPECT_TRUE(typedOrphan == nullptr); } } { Orphan> typedOrphan = orphan.releaseAs>(); checkList(typedOrphan.getReader(), {12, 34, 56}); checkList(typedOrphan.get(), {12, 34, 56}); } } TEST(Orphans, DynamicAnyPointer) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root.getAnyPointerField().initAs()); EXPECT_TRUE(root.hasAnyPointerField()); Orphan orphan = root.getAnyPointerField().disown(); EXPECT_EQ(DynamicValue::ANY_POINTER, orphan.getType()); Orphan objectOrphan = orphan.releaseAs(); checkTestMessage(objectOrphan.getAs()); checkDynamicTestMessage(objectOrphan.getAs(Schema::from())); } TEST(Orphans, DynamicDisown) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); Orphan dstOrphan = Orphanage::getForMessageContaining(root).newOrphan(); auto dst = dstOrphan.get(); DynamicStruct::Builder dynamic = root; DynamicStruct::Builder dynamicDst = dst; for (auto field: dynamic.getSchema().getFields()) { dynamicDst.adopt(field, dynamic.disown(field)); } checkTestMessageAllZero(root.asReader()); checkTestMessage(dst.asReader()); for (auto field: dynamic.getSchema().getFields()) { dynamicDst.adopt(field, dynamic.disown(field)); } checkTestMessageAllZero(root.asReader()); checkTestMessageAllZero(dst.asReader()); } TEST(Orphans, DynamicDisownGroup) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto bar = root.initGroups().initBar(); bar.setCorge(123); bar.setGrault("foo"); bar.setGarply(9876543210987ll); Orphan dstOrphan = Orphanage::getForMessageContaining(root).newOrphan(); auto dst = dstOrphan.get(); toDynamic(dst).adopt("groups", toDynamic(root).disown("groups")); EXPECT_EQ(test::TestGroups::Groups::FOO, root.getGroups().which()); EXPECT_EQ(test::TestGroups::Groups::BAR, dst.getGroups().which()); auto newBar = dst.getGroups().getBar(); EXPECT_EQ(123, newBar.getCorge()); EXPECT_EQ("foo", newBar.getGrault()); EXPECT_EQ(9876543210987ll, newBar.getGarply()); } #endif // !CAPNP_LITE TEST(Orphans, OrphanageFromBuilder) { MallocMessageBuilder builder; auto root = builder.initRoot(); { Orphanage orphanage = Orphanage::getForMessageContaining(root); Orphan orphan = orphanage.newOrphan(); initTestMessage(orphan.get()); root.adoptStructField(kj::mv(orphan)); checkTestMessage(root.asReader().getStructField()); } { Orphanage orphanage = Orphanage::getForMessageContaining(root.initBoolList(3)); Orphan orphan = orphanage.newOrphan(); initTestMessage(orphan.get()); root.adoptStructField(kj::mv(orphan)); checkTestMessage(root.asReader().getStructField()); } #if !CAPNP_LITE { Orphanage orphanage = Orphanage::getForMessageContaining(toDynamic(root)); Orphan orphan = orphanage.newOrphan(); initTestMessage(orphan.get()); root.adoptStructField(kj::mv(orphan)); checkTestMessage(root.asReader().getStructField()); } { Orphanage orphanage = Orphanage::getForMessageContaining(toDynamic(root.initBoolList(3))); Orphan orphan = orphanage.newOrphan(); initTestMessage(orphan.get()); root.adoptStructField(kj::mv(orphan)); checkTestMessage(root.asReader().getStructField()); } #endif // !CAPNP_LITE } static bool allZero(const word* begin, const word* end) { for (const byte* pos = reinterpret_cast(begin); pos < reinterpret_cast(end); ++pos) { if (*pos != 0) return false; } return true; } TEST(Orphans, StructsZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); initTestMessage(root.initStructField()); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownStructField(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, ListsZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); root.setUInt32List({12, 34, 56}); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownUInt32List(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, EmptyListsZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); root.initUInt32List(0); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownUInt32List(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, StructListsZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); { auto list = root.initStructList(2); initTestMessage(list[0]); initTestMessage(list[1]); } const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownStructList(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, EmptyStructListsZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); root.initStructList(0); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownStructList(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, TextZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); root.setTextField("abcd123"); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setDataField(data("foo")); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownTextField(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ(data("foo"), root.getDataField()); } TEST(Orphans, DataZerodAfterUse) { MallocMessageBuilder builder; auto root = builder.initRoot(); const word* zerosStart = builder.getSegmentsForOutput()[0].end(); root.setDataField(data("abcd123")); const word* zerosEnd = builder.getSegmentsForOutput()[0].end(); root.setTextField("foo"); // guard against overruns EXPECT_EQ(1u, builder.getSegmentsForOutput().size()); // otherwise test is invalid root.disownDataField(); EXPECT_TRUE(allZero(zerosStart, zerosEnd)); EXPECT_EQ("foo", root.getTextField()); } TEST(Orphans, FarPointer) { MallocMessageBuilder builder(0, AllocationStrategy::FIXED_SIZE); auto root = builder.initRoot(); auto child = root.initStructField(); initTestMessage(child); auto orphan = root.disownStructField(); EXPECT_FALSE(root.hasStructField()); EXPECT_TRUE(orphan != nullptr); EXPECT_FALSE(orphan == nullptr); checkTestMessage(orphan.getReader()); checkTestMessage(orphan.get()); } TEST(Orphans, UpgradeStruct) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto old = root.getAnyPointerField().initAs(); old.setOld1(1234); old.setOld2("foo"); auto orphan = root.getAnyPointerField().disownAs(); // Relocation has not occurred yet. old.setOld1(12345); EXPECT_EQ(12345, orphan.getReader().getOld1()); EXPECT_EQ("foo", old.getOld2()); // This will relocate the struct. auto newVersion = orphan.get(); EXPECT_EQ(0, old.getOld1()); EXPECT_EQ("", old.getOld2()); EXPECT_EQ(12345, newVersion.getOld1()); EXPECT_EQ("foo", newVersion.getOld2()); } TEST(Orphans, UpgradeStructList) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto old = root.getAnyPointerField().initAs>(2); old[0].setOld1(1234); old[0].setOld2("foo"); old[1].setOld1(4321); old[1].setOld2("bar"); auto orphan = root.getAnyPointerField().disownAs>(); // Relocation has not occurred yet. old[0].setOld1(12345); EXPECT_EQ(12345, orphan.getReader()[0].getOld1()); EXPECT_EQ("foo", old[0].getOld2()); // This will relocate the struct. auto newVersion = orphan.get(); EXPECT_EQ(0, old[0].getOld1()); EXPECT_EQ("", old[0].getOld2()); EXPECT_EQ(12345, newVersion[0].getOld1()); EXPECT_EQ("foo", newVersion[0].getOld2()); EXPECT_EQ(4321, newVersion[1].getOld1()); EXPECT_EQ("bar", newVersion[1].getOld2()); } TEST(Orphans, DisownNull) { MallocMessageBuilder builder; auto root = builder.initRoot(); { Orphan orphan = root.disownStructField(); EXPECT_TRUE(orphan == nullptr); checkTestMessageAllZero(orphan.getReader()); EXPECT_TRUE(orphan == nullptr); // get()ing the orphan allocates an object, for security reasons. checkTestMessageAllZero(orphan.get()); EXPECT_FALSE(orphan == nullptr); } { Orphan> orphan = root.disownInt32List(); EXPECT_TRUE(orphan == nullptr); EXPECT_EQ(0, orphan.getReader().size()); EXPECT_TRUE(orphan == nullptr); EXPECT_EQ(0, orphan.get().size()); EXPECT_TRUE(orphan == nullptr); } { Orphan> orphan = root.disownStructList(); EXPECT_TRUE(orphan == nullptr); EXPECT_EQ(0, orphan.getReader().size()); EXPECT_TRUE(orphan == nullptr); EXPECT_EQ(0, orphan.get().size()); EXPECT_TRUE(orphan == nullptr); } } TEST(Orphans, ReferenceExternalData) { MallocMessageBuilder builder; union { word align; byte data[50]; }; memset(data, 0x55, sizeof(data)); auto orphan = builder.getOrphanage().referenceExternalData(Data::Builder(data, sizeof(data))); // Data was added as a new segment. { auto segments = builder.getSegmentsForOutput(); ASSERT_EQ(2, segments.size()); EXPECT_EQ(data, segments[1].asBytes().begin()); EXPECT_EQ((sizeof(data) + 7) / 8, segments[1].size()); } // Can't get builder because it's read-only. EXPECT_ANY_THROW(orphan.get()); // Can get reader. { auto reader = orphan.getReader(); EXPECT_EQ(data, reader.begin()); EXPECT_EQ(sizeof(data), reader.size()); } // Adopt into message tree. auto root = builder.getRoot(); root.adoptDataField(kj::mv(orphan)); // Can't get child builder. EXPECT_ANY_THROW(root.getDataField()); // Can get child reader. { auto reader = root.asReader().getDataField(); EXPECT_EQ(data, reader.begin()); EXPECT_EQ(sizeof(data), reader.size()); } // Back to orphan. orphan = root.disownDataField(); // Now the orphan may be pointing to a far pointer landing pad, so check that it still does the // right things. // Can't get builder because it's read-only. EXPECT_ANY_THROW(orphan.get()); // Can get reader. { auto reader = orphan.getReader(); EXPECT_EQ(data, reader.begin()); EXPECT_EQ(sizeof(data), reader.size()); } // Finally, let's abandon the orphan and check that this doesn't zero out the data. orphan = Orphan(); for (byte b: data) { EXPECT_EQ(0x55, b); } } TEST(Orphans, ReferenceExternalData_NoZeroOnSet) { // Verify that an external blob is not zeroed by setFoo(). union { word align; byte data[50]; }; memset(data, 0x55, sizeof(data)); MallocMessageBuilder builder; auto root = builder.getRoot(); root.adoptDataField(builder.getOrphanage().referenceExternalData( Data::Builder(data, sizeof(data)))); root.setDataField(Data::Builder()); for (byte b: data) { EXPECT_EQ(0x55, b); } } TEST(Orphans, ReferenceExternalData_NoZeroImmediateAbandon) { // Verify that an external blob is not zeroed when abandoned immediately, without ever being // adopted. union { word align; byte data[50]; }; memset(data, 0x55, sizeof(data)); MallocMessageBuilder builder; builder.getOrphanage().referenceExternalData(Data::Builder(data, sizeof(data))); for (byte b: data) { EXPECT_EQ(0x55, b); } } TEST(Orphans, TruncateData) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 123, builder.size()); EXPECT_EQ(4, message.getSegmentsForOutput()[0].size()); orphan.truncate(2); EXPECT_EQ(2, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(2, reader.size()); EXPECT_EQ(builder.begin(), reader.begin()); EXPECT_EQ(123, builder[0]); EXPECT_EQ(123, builder[1]); EXPECT_EQ(0, builder[2]); EXPECT_EQ(0, builder[3]); EXPECT_EQ(0, builder[16]); } TEST(Orphans, ExtendData) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 123, builder.size()); EXPECT_EQ(4, message.getSegmentsForOutput()[0].size()); orphan.truncate(27); EXPECT_EQ(5, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(27, reader.size()); EXPECT_EQ(builder.begin(), reader.begin()); for (uint i = 0; i < 17; i++) { EXPECT_EQ(123, reader[i]); } for (uint i = 17; i < 27; i++) { EXPECT_EQ(0, reader[i]); } } TEST(Orphans, ExtendDataCopy) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 123, builder.size()); auto orphan2 = message.getOrphanage().newOrphan(1); orphan2.get()[0] = 32; orphan.truncate(27); auto reader = orphan.getReader(); EXPECT_EQ(27, reader.size()); EXPECT_NE(builder.begin(), reader.begin()); for (uint i = 0; i < 17; i++) { EXPECT_EQ(123, reader[i]); EXPECT_EQ(0, builder[i]); } for (uint i = 17; i < 27; i++) { EXPECT_EQ(0, reader[i]); } EXPECT_EQ(32, orphan2.getReader()[0]); } TEST(Orphans, ExtendDataFromEmpty) { MallocMessageBuilder message; auto orphan = message.initRoot().disownDataField(); orphan.truncate(3); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ(0, reader[i]); } } TEST(Orphans, TruncateText) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 'a', builder.size()); EXPECT_EQ(4, message.getSegmentsForOutput()[0].size()); orphan.truncate(2); EXPECT_EQ(2, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(2, reader.size()); EXPECT_EQ(builder.begin(), reader.begin()); EXPECT_EQ('a', builder[0]); EXPECT_EQ('a', builder[1]); EXPECT_EQ('\0', builder[2]); EXPECT_EQ('\0', builder[3]); EXPECT_EQ('\0', builder[16]); } TEST(Orphans, ExtendText) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 'a', builder.size()); EXPECT_EQ(4, message.getSegmentsForOutput()[0].size()); orphan.truncate(27); EXPECT_EQ(5, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(27, reader.size()); EXPECT_EQ(builder.begin(), reader.begin()); for (uint i = 0; i < 17; i++) { EXPECT_EQ('a', reader[i]); } for (uint i = 17; i < 27; i++) { EXPECT_EQ('\0', reader[i]); } } TEST(Orphans, ExtendTextCopy) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan(17); auto builder = orphan.get(); memset(builder.begin(), 'a', builder.size()); auto orphan2 = message.getOrphanage().newOrphan(1); orphan2.get()[0] = 32; orphan.truncate(27); auto reader = orphan.getReader(); EXPECT_EQ(27, reader.size()); EXPECT_NE(builder.begin(), reader.begin()); for (uint i = 0; i < 17; i++) { EXPECT_EQ('a', reader[i]); EXPECT_EQ('\0', builder[i]); } for (uint i = 17; i < 27; i++) { EXPECT_EQ('\0', reader[i]); } EXPECT_EQ(32, orphan2.getReader()[0]); } TEST(Orphans, ExtendTextFromEmpty) { MallocMessageBuilder message; auto orphan = message.initRoot().disownTextField(); orphan.truncate(3); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ('\0', reader[i]); } } TEST(Orphans, TruncatePrimitiveList) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.set(i, 123456789 + i); } EXPECT_EQ(5, message.getSegmentsForOutput()[0].size()); orphan.truncate(3); EXPECT_EQ(3, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ(123456789 + i, builder[i]); EXPECT_EQ(123456789 + i, reader[i]); } for (uint i = 3; i < 7; i++) { EXPECT_EQ(0, builder[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, 321); EXPECT_EQ(321, reader[0]); } TEST(Orphans, ExtendPrimitiveList) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.set(i, 123456789 + i); } EXPECT_EQ(5, message.getSegmentsForOutput()[0].size()); orphan.truncate(11); EXPECT_EQ(7, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(123456789 + i, reader[i]); EXPECT_EQ(123456789 + i, builder[i]); } for (uint i = 7; i < 11; i++) { EXPECT_EQ(0, reader[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, 321); EXPECT_EQ(321, reader[0]); } TEST(Orphans, ExtendPrimitiveListCopy) { MallocMessageBuilder message; auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.set(i, 123456789 + i); } auto orphan2 = message.getOrphanage().newOrphan(1); orphan2.get()[0] = 32; orphan.truncate(11); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(123456789 + i, reader[i]); EXPECT_EQ(0, builder[i]); } for (uint i = 7; i < 11; i++) { EXPECT_EQ(0, reader[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, 321); EXPECT_EQ(123456789, reader[0]); EXPECT_EQ(32, orphan2.getReader()[0]); } TEST(Orphans, ExtendPointerListFromEmpty) { MallocMessageBuilder message; auto orphan = message.initRoot().disownUInt32List(); orphan.truncate(3); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ(0, reader[i]); } } TEST(Orphans, TruncatePointerList) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { pointers.add(message.getOrphanage().newOrphanCopy(Text::Reader(kj::str("foo", i)))); } size_t sizeBeforeList = message.getSegmentsForOutput()[0].size(); auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adopt(i, kj::mv(pointers[i])); } EXPECT_EQ(sizeBeforeList + 7, message.getSegmentsForOutput()[0].size()); orphan.truncate(3); EXPECT_EQ(sizeBeforeList + 3, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ(kj::str("foo", i), builder[i]); EXPECT_EQ(kj::str("foo", i), reader[i]); } for (uint i = 3; i < 7; i++) { EXPECT_TRUE(builder[i] == nullptr); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, "bar"); EXPECT_EQ("bar", reader[0]); } TEST(Orphans, ExtendPointerList) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { pointers.add(message.getOrphanage().newOrphanCopy(Text::Reader(kj::str("foo", i)))); } size_t sizeBeforeList = message.getSegmentsForOutput()[0].size(); auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adopt(i, kj::mv(pointers[i])); } EXPECT_EQ(sizeBeforeList + 7, message.getSegmentsForOutput()[0].size()); orphan.truncate(11); EXPECT_EQ(sizeBeforeList + 11, message.getSegmentsForOutput()[0].size()); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(kj::str("foo", i), reader[i]); EXPECT_EQ(kj::str("foo", i), builder[i]); } for (uint i = 7; i < 11; i++) { EXPECT_TRUE(reader[i] == nullptr); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, "bar"); EXPECT_EQ("bar", reader[0]); } TEST(Orphans, ExtendPointerListCopy) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { pointers.add(message.getOrphanage().newOrphanCopy(Text::Reader(kj::str("foo", i)))); } auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adopt(i, kj::mv(pointers[i])); } auto orphan2 = message.getOrphanage().newOrphan(1); orphan2.get()[0] = 32; orphan.truncate(11); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(kj::str("foo", i), reader[i]); EXPECT_TRUE(builder[i] == nullptr); } for (uint i = 7; i < 11; i++) { EXPECT_TRUE(reader[i] == nullptr); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder.set(0, "bar"); EXPECT_EQ("foo0", reader[0]); EXPECT_EQ(32, orphan2.getReader()[0]); } TEST(Orphans, ExtendPointerListFromEmpty) { MallocMessageBuilder message; auto orphan = message.initRoot().disownTextList(); orphan.truncate(3); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ("", reader[i]); } } TEST(Orphans, TruncateStructList) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { auto o = message.getOrphanage().newOrphan(); auto b = o.get(); b.setUInt32Field(123456789 + i); b.setTextField(kj::str("foo", i)); b.setUInt8List({123, 45}); pointers.add(kj::mv(o)); } auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adoptWithCaveats(i, kj::mv(pointers[i])); } size_t sizeBeforeTruncate = message.getSegmentsForOutput()[0].size(); orphan.truncate(3); EXPECT_LT(message.getSegmentsForOutput()[0].size(), sizeBeforeTruncate); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { EXPECT_EQ(123456789 + i, reader[i].getUInt32Field()); EXPECT_EQ(kj::str("foo", i), reader[i].getTextField()); checkList(reader[i].getUInt8List(), {123, 45}); EXPECT_EQ(123456789 + i, builder[i].getUInt32Field()); EXPECT_EQ(kj::str("foo", i), builder[i].getTextField()); checkList(builder[i].getUInt8List(), {123, 45}); } for (uint i = 3; i < 7; i++) { checkTestMessageAllZero(builder[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder[0].setUInt32Field(321); EXPECT_EQ(321, reader[0].getUInt32Field()); } TEST(Orphans, ExtendStructList) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { auto o = message.getOrphanage().newOrphan(); auto b = o.get(); b.setUInt32Field(123456789 + i); b.setTextField(kj::str("foo", i)); b.setUInt8List({123, 45}); pointers.add(kj::mv(o)); } auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adoptWithCaveats(i, kj::mv(pointers[i])); } orphan.truncate(11); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(123456789 + i, reader[i].getUInt32Field()); EXPECT_EQ(kj::str("foo", i), reader[i].getTextField()); checkList(reader[i].getUInt8List(), {123, 45}); EXPECT_EQ(123456789 + i, builder[i].getUInt32Field()); EXPECT_EQ(kj::str("foo", i), builder[i].getTextField()); checkList(builder[i].getUInt8List(), {123, 45}); } for (uint i = 7; i < 11; i++) { checkTestMessageAllZero(reader[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder[0].setUInt32Field(321); EXPECT_EQ(321, reader[0].getUInt32Field()); } TEST(Orphans, ExtendStructListCopy) { MallocMessageBuilder message; // Allocate data in advance so that the list itself is at the end of the segment. kj::Vector> pointers(7); for (uint i = 0; i < 7; i++) { auto o = message.getOrphanage().newOrphan(); auto b = o.get(); b.setUInt32Field(123456789 + i); b.setTextField(kj::str("foo", i)); b.setUInt8List({123, 45}); pointers.add(kj::mv(o)); } auto orphan = message.getOrphanage().newOrphan>(7); auto builder = orphan.get(); for (uint i = 0; i < 7; i++) { builder.adoptWithCaveats(i, kj::mv(pointers[i])); } auto orphan2 = message.getOrphanage().newOrphan(1); orphan2.get()[0] = 32; orphan.truncate(11); auto reader = orphan.getReader(); EXPECT_EQ(11, reader.size()); for (uint i = 0; i < 7; i++) { EXPECT_EQ(123456789 + i, reader[i].getUInt32Field()); EXPECT_EQ(kj::str("foo", i), reader[i].getTextField()); checkList(reader[i].getUInt8List(), {123, 45}); checkTestMessageAllZero(builder[i]); } for (uint i = 7; i < 11; i++) { checkTestMessageAllZero(reader[i]); } // Can't compare pointers directly, but we can check if builder modifications are visible using // the reader. builder[0].setUInt32Field(321); EXPECT_EQ(123456789, reader[0].getUInt32Field()); EXPECT_EQ(32, orphan2.getReader()[0]); } TEST(Orphans, ExtendStructListFromEmpty) { MallocMessageBuilder message; auto orphan = message.initRoot().disownStructList(); orphan.truncate(3); auto reader = orphan.getReader(); EXPECT_EQ(3, reader.size()); for (uint i = 0; i < 3; i++) { checkTestMessageAllZero(reader[i]); } } template void initList(ListBuilder builder, std::initializer_list>>> values) { KJ_ASSERT(builder.size() == values.size()); size_t i = 0; for (auto& value: values) { builder.set(i++, value); } } TEST(Orphans, ConcatenatePrimitiveLists) { MallocMessageBuilder message; auto orphanage = message.getOrphanage(); auto list1 = orphanage.newOrphan>(3); initList(list1.get(), {12, 34, 56}); auto list2 = orphanage.newOrphan>(2); initList(list2.get(), {78, 90}); auto list3 = orphanage.newOrphan>(4); initList(list3.get(), {23, 45, 67, 89}); List::Reader lists[] = { list1.getReader(), list2.getReader(), list3.getReader() }; kj::ArrayPtr::Reader> array = lists; auto cat = message.getOrphanage().newOrphanConcat(array); checkList(cat.getReader(), {12, 34, 56, 78, 90, 23, 45, 67, 89}); } TEST(Orphans, ConcatenateBitLists) { MallocMessageBuilder message; auto orphanage = message.getOrphanage(); auto list1 = orphanage.newOrphan>(3); initList(list1.get(), {true, true, false}); auto list2 = orphanage.newOrphan>(2); initList(list2.get(), {false, true}); auto list3 = orphanage.newOrphan>(4); initList(list3.get(), {false, false, true, false}); List::Reader lists[] = { list1.getReader(), list2.getReader(), list3.getReader() }; kj::ArrayPtr::Reader> array = lists; auto cat = message.getOrphanage().newOrphanConcat(array); checkList(cat.getReader(), {true, true, false, false, true, false, false, true, false}); } TEST(Orphans, ConcatenatePointerLists) { MallocMessageBuilder message; auto orphanage = message.getOrphanage(); auto list1 = orphanage.newOrphan>(3); initList(list1.get(), {"foo", "bar", "baz"}); auto list2 = orphanage.newOrphan>(2); initList(list2.get(), {"qux", "corge"}); auto list3 = orphanage.newOrphan>(4); initList(list3.get(), {"grault", "garply", "waldo", "fred"}); List::Reader lists[] = { list1.getReader(), list2.getReader(), list3.getReader() }; kj::ArrayPtr::Reader> array = lists; auto cat = message.getOrphanage().newOrphanConcat(array); checkList(cat.getReader(), { "foo", "bar", "baz", "qux", "corge", "grault", "garply", "waldo", "fred"}); } TEST(Orphans, ConcatenateStructLists) { // In this test, we not only concatenate two struct lists, but we concatenate in a list that // contains a newer-than-expected version of the struct with extra fields, in order to verify // that the new fields aren't lost. MallocMessageBuilder message; auto orphanage = message.getOrphanage(); auto orphan1 = orphanage.newOrphan>(2); auto list1 = orphan1.get(); list1[0].setOld1(12); list1[0].setOld2("foo"); list1[1].setOld1(34); list1[1].setOld2("bar"); auto orphan2 = orphanage.newOrphan(); auto list2 = orphan2.get().getAnyPointerField().initAs>(2); list2[0].setOld1(56); list2[0].setOld2("baz"); list2[0].setNew1(123); list2[0].setNew2("corge"); list2[1].setOld1(78); list2[1].setOld2("qux"); list2[1].setNew1(456); list2[1].setNew2("grault"); List::Reader lists[] = { orphan1.getReader(), orphan2.getReader().getAnyPointerField().getAs>() }; kj::ArrayPtr::Reader> array = lists; auto orphan3 = orphanage.newOrphan(); orphan3.get().getAnyPointerField().adopt(message.getOrphanage().newOrphanConcat(array)); auto cat = orphan3.getReader().getAnyPointerField().getAs>(); ASSERT_EQ(4, cat.size()); EXPECT_EQ(12, cat[0].getOld1()); EXPECT_EQ("foo", cat[0].getOld2()); EXPECT_EQ(987, cat[0].getNew1()); EXPECT_FALSE(cat[0].hasNew2()); EXPECT_EQ(34, cat[1].getOld1()); EXPECT_EQ("bar", cat[1].getOld2()); EXPECT_EQ(987, cat[1].getNew1()); EXPECT_FALSE(cat[1].hasNew2()); EXPECT_EQ(56, cat[2].getOld1()); EXPECT_EQ("baz", cat[2].getOld2()); EXPECT_EQ(123, cat[2].getNew1()); EXPECT_EQ("corge", cat[2].getNew2()); EXPECT_EQ(78, cat[3].getOld1()); EXPECT_EQ("qux", cat[3].getOld2()); EXPECT_EQ(456, cat[3].getNew1()); EXPECT_EQ("grault", cat[3].getNew2()); } TEST(Orphans, ConcatenateStructListsUpgradeFromPrimitive) { // Like above, but we're "upgrading" a primitive list to a struct list. MallocMessageBuilder message; auto orphanage = message.getOrphanage(); auto orphan1 = orphanage.newOrphan>(2); auto list1 = orphan1.get(); list1[0].setOld1(12); list1[0].setOld2("foo"); list1[1].setOld1(34); list1[1].setOld2("bar"); auto orphan2 = orphanage.newOrphan(); auto list2 = orphan2.get().getAnyPointerField().initAs>(2); initList(list2, {12345, 67890}); List::Reader lists[] = { orphan1.getReader(), orphan2.getReader().getAnyPointerField().getAs>() }; kj::ArrayPtr::Reader> array = lists; auto orphan3 = message.getOrphanage().newOrphanConcat(array); auto cat = orphan3.getReader(); ASSERT_EQ(4, cat.size()); EXPECT_EQ(12, cat[0].getOld1()); EXPECT_EQ("foo", cat[0].getOld2()); EXPECT_EQ(34, cat[1].getOld1()); EXPECT_EQ("bar", cat[1].getOld2()); EXPECT_EQ(12345, cat[2].getOld1()); EXPECT_FALSE(cat[2].hasOld2()); EXPECT_EQ(67890, cat[3].getOld1()); EXPECT_FALSE(cat[3].hasOld2()); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/dynamic-test.c++0000644000175000017500000004416114731420004021526 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "dynamic.h" #include "message.h" #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { template void checkList(T reader, std::initializer_list> expected) { auto list = reader.template as(); ASSERT_EQ(expected.size(), list.size()); for (uint i = 0; i < expected.size(); i++) { EXPECT_EQ(expected.begin()[i], list[i].template as()); } auto typed = reader.template as>(); ASSERT_EQ(expected.size(), typed.size()); for (uint i = 0; i < expected.size(); i++) { EXPECT_EQ(expected.begin()[i], typed[i]); } } TEST(DynamicApi, Build) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); initDynamicTestMessage(root); checkTestMessage(root.asReader().as()); checkDynamicTestMessage(root.asReader()); checkDynamicTestMessage(root); } TEST(DynamicApi, Read) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); checkDynamicTestMessage(toDynamic(root.asReader())); checkDynamicTestMessage(toDynamic(root).asReader()); checkDynamicTestMessage(toDynamic(root)); } TEST(DynamicApi, Defaults) { AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}}; kj::ArrayPtr segments[1] = {kj::arrayPtr(nullRoot.words, 1)}; SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); auto root = reader.getRoot(Schema::from()); checkDynamicTestMessage(root); } TEST(DynamicApi, DefaultsBuilder) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); checkTestMessage(root.asReader().as()); checkDynamicTestMessage(root.asReader()); // This will initialize the whole message, replacing null pointers with copies of defaults. checkDynamicTestMessage(root); // Check again now that the message is initialized. checkTestMessage(root.asReader().as()); checkDynamicTestMessage(root.asReader()); checkDynamicTestMessage(root); } TEST(DynamicApi, Zero) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); checkDynamicTestMessageAllZero(root.asReader()); checkTestMessageAllZero(root.asReader().as()); checkDynamicTestMessageAllZero(root); checkTestMessageAllZero(root.asReader().as()); } TEST(DynamicApi, ListListsBuild) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); initDynamicTestLists(root); checkTestMessage(root.asReader().as()); checkDynamicTestLists(root.asReader()); checkDynamicTestLists(root); } TEST(DynamicApi, ListListsRead) { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); checkDynamicTestLists(toDynamic(root.asReader())); checkDynamicTestLists(toDynamic(root).asReader()); checkDynamicTestLists(toDynamic(root)); } TEST(DynamicApi, AnyPointers) { MallocMessageBuilder builder; auto root = builder.getRoot(); initDynamicTestMessage( root.getAnyPointerField().initAs(Schema::from())); checkTestMessage(root.asReader().getAnyPointerField().getAs()); checkDynamicTestMessage( root.asReader().getAnyPointerField().getAs(Schema::from())); checkDynamicTestMessage( root.getAnyPointerField().getAs(Schema::from())); { { auto list = root.getAnyPointerField().initAs(Schema::from>(), 4); list.set(0, 123); list.set(1, 456); list.set(2, 789); list.set(3, 123456789); } { auto list = root.asReader().getAnyPointerField().getAs>(); ASSERT_EQ(4u, list.size()); EXPECT_EQ(123u, list[0]); EXPECT_EQ(456u, list[1]); EXPECT_EQ(789u, list[2]); EXPECT_EQ(123456789u, list[3]); } checkList(root.asReader().getAnyPointerField().getAs( Schema::from>()), {123u, 456u, 789u, 123456789u}); checkList(root.getAnyPointerField().getAs( Schema::from>()), {123u, 456u, 789u, 123456789u}); } // Setting an AnyPointer to various types should work. toDynamic(root).set("anyPointerField", capnp::Text::Reader("foo")); EXPECT_EQ("foo", root.getAnyPointerField().getAs()); { auto orphan = builder.getOrphanage().newOrphan(); initTestMessage(orphan.get()); toDynamic(root).set("anyPointerField", orphan.getReader()); checkTestMessage(root.getAnyPointerField().getAs()); toDynamic(root).adopt("anyPointerField", kj::mv(orphan)); checkTestMessage(root.getAnyPointerField().getAs()); } { auto lorphan = builder.getOrphanage().newOrphan>(3); lorphan.get().set(0, 12); lorphan.get().set(1, 34); lorphan.get().set(2, 56); toDynamic(root).set("anyPointerField", lorphan.getReader()); auto l = root.getAnyPointerField().getAs>(); ASSERT_EQ(3, l.size()); EXPECT_EQ(12, l[0]); EXPECT_EQ(34, l[1]); EXPECT_EQ(56, l[2]); } // Just compile this one. toDynamic(root).set("anyPointerField", Capability::Client(nullptr)); root.getAnyPointerField().getAs(); } TEST(DynamicApi, DynamicAnyPointers) { MallocMessageBuilder builder; auto root = builder.getRoot(Schema::from()); initDynamicTestMessage( root.get("anyPointerField").as() .initAs(Schema::from())); checkTestMessage( root.asReader().as().getAnyPointerField().getAs()); checkDynamicTestMessage( root.asReader().get("anyPointerField").as() .getAs(Schema::from())); checkDynamicTestMessage( root.asReader().get("anyPointerField").as() .getAs(Schema::from())); checkDynamicTestMessage( root.get("anyPointerField").as().asReader() .getAs(Schema::from())); checkDynamicTestMessage( root.get("anyPointerField").as() .getAs(Schema::from())); { { auto list = root.init("anyPointerField").as() .initAs(Schema::from>(), 4); list.set(0, 123); list.set(1, 456); list.set(2, 789); list.set(3, 123456789); } { auto list = root.asReader().as() .getAnyPointerField().getAs>(); ASSERT_EQ(4u, list.size()); EXPECT_EQ(123u, list[0]); EXPECT_EQ(456u, list[1]); EXPECT_EQ(789u, list[2]); EXPECT_EQ(123456789u, list[3]); } checkList( root.asReader().get("anyPointerField").as() .getAs(Schema::from>()), {123u, 456u, 789u, 123456789u}); checkList( root.asReader().get("anyPointerField").as() .getAs(Schema::from>()), {123u, 456u, 789u, 123456789u}); checkList( root.get("anyPointerField").as().asReader() .getAs(Schema::from>()), {123u, 456u, 789u, 123456789u}); checkList( root.get("anyPointerField").as() .getAs(Schema::from>()), {123u, 456u, 789u, 123456789u}); } } TEST(DynamicApi, DynamicAnyStructs) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.as().as().setInt8Field(123); EXPECT_EQ(root.get("int8Field").as(), 123); EXPECT_EQ(root.asReader().as().as().getInt8Field(), 123); } #define EXPECT_MAYBE_EQ(name, exp, expected, actual) \ KJ_IF_MAYBE(name, exp) { \ EXPECT_EQ(expected, actual); \ } else { \ KJ_FAIL_EXPECT("Maybe was empty."); \ } TEST(DynamicApi, UnionsRead) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getUnion0().setU0f1s32(1234567); root.getUnion1().setU1f1sp("foo"); root.getUnion2().setU2f0s1(true); root.getUnion3().setU3f0s64(1234567890123456789ll); { auto dynamic = toDynamic(root.asReader()); { auto u = dynamic.get("union0").as(); EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName()); EXPECT_EQ(1234567, u.get("u0f1s32").as()); } { auto u = dynamic.get("union1").as(); EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName()); EXPECT_EQ("foo", u.get("u1f1sp").as()); } { auto u = dynamic.get("union2").as(); EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName()); EXPECT_TRUE(u.get("u2f0s1").as()); } { auto u = dynamic.get("union3").as(); EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName()); EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as()); } } { // Again as a builder. auto dynamic = toDynamic(root); { auto u = dynamic.get("union0").as(); EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName()); EXPECT_EQ(1234567, u.get("u0f1s32").as()); } { auto u = dynamic.get("union1").as(); EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName()); EXPECT_EQ("foo", u.get("u1f1sp").as()); } { auto u = dynamic.get("union2").as(); EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName()); EXPECT_TRUE(u.get("u2f0s1").as()); } { auto u = dynamic.get("union3").as(); EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName()); EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as()); } } } TEST(DynamicApi, UnionsWrite) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.get("union0").as().set("u0f1s32", 1234567); root.get("union1").as().set("u1f1sp", "foo"); root.get("union2").as().set("u2f0s1", true); root.get("union3").as().set("u3f0s64", 1234567890123456789ll); auto reader = root.asReader().as(); ASSERT_EQ(TestUnion::Union0::U0F1S32, reader.getUnion0().which()); EXPECT_EQ(1234567, reader.getUnion0().getU0f1s32()); ASSERT_EQ(TestUnion::Union1::U1F1SP, reader.getUnion1().which()); EXPECT_EQ("foo", reader.getUnion1().getU1f1sp()); ASSERT_EQ(TestUnion::Union2::U2F0S1, reader.getUnion2().which()); EXPECT_TRUE(reader.getUnion2().getU2f0s1()); ASSERT_EQ(TestUnion::Union3::U3F0S64, reader.getUnion3().which()); EXPECT_EQ(1234567890123456789ll, reader.getUnion3().getU3f0s64()); // Can't access union members by name from the root. EXPECT_ANY_THROW(root.get("u0f1s32")); EXPECT_ANY_THROW(root.set("u0f1s32", 1234567)); } TEST(DynamicApi, UnnamedUnion) { MallocMessageBuilder builder; StructSchema schema = Schema::from(); auto root = builder.initRoot(schema); EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which())); root.set("bar", 321); EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which())); EXPECT_EQ(321u, root.get("bar").as()); EXPECT_EQ(321u, root.asReader().get("bar").as()); EXPECT_ANY_THROW(root.get("foo")); EXPECT_ANY_THROW(root.asReader().get("foo")); root.set("foo", 123); EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which())); EXPECT_EQ(123u, root.get("foo").as()); EXPECT_EQ(123u, root.asReader().get("foo").as()); EXPECT_ANY_THROW(root.get("bar")); EXPECT_ANY_THROW(root.asReader().get("bar")); root.set("bar", 321); EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which())); EXPECT_EQ(321u, root.get("bar").as()); EXPECT_EQ(321u, root.asReader().get("bar").as()); EXPECT_ANY_THROW(root.get("foo")); EXPECT_ANY_THROW(root.asReader().get("foo")); root.set("foo", 123); EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which())); EXPECT_EQ(123u, root.get("foo").as()); EXPECT_EQ(123u, root.asReader().get("foo").as()); EXPECT_ANY_THROW(root.get("bar")); EXPECT_ANY_THROW(root.asReader().get("bar")); } TEST(DynamicApi, ConversionFailures) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.set("int8Field", 123); EXPECT_NONFATAL_FAILURE(root.set("int8Field", 1234)); root.set("uInt32Field", 1); EXPECT_NONFATAL_FAILURE(root.set("uInt32Field", -1)); root.set("int16Field", 5); EXPECT_NONFATAL_FAILURE(root.set("int16Field", 0.5)); root.set("boolField", true); EXPECT_NONFATAL_FAILURE(root.set("boolField", 1)); } TEST(DynamicApi, LateUnion) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.get("theUnion").as().set("qux", "hello"); EXPECT_EQ("hello", root.as().getTheUnion().getQux()); } TEST(DynamicApi, Has) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); // Primitive fields are always present even if set to default. EXPECT_TRUE(root.has("int32Field")); EXPECT_FALSE(root.has("int32Field", HasMode::NON_DEFAULT)); root.set("int32Field", 123); EXPECT_TRUE(root.has("int32Field")); EXPECT_TRUE(root.has("int32Field", HasMode::NON_DEFAULT)); root.set("int32Field", -12345678); EXPECT_TRUE(root.has("int32Field")); EXPECT_FALSE(root.has("int32Field", HasMode::NON_DEFAULT)); // Pointers are absent until initialized. EXPECT_FALSE(root.has("structField")); EXPECT_FALSE(root.has("structField", HasMode::NON_DEFAULT)); root.init("structField"); EXPECT_TRUE(root.has("structField")); EXPECT_TRUE(root.has("structField", HasMode::NON_DEFAULT)); } TEST(DynamicApi, HasWhenEmpty) { AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}}; kj::ArrayPtr segments[1] = {kj::arrayPtr(nullRoot.words, 1)}; SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); auto root = reader.getRoot(Schema::from()); EXPECT_TRUE(root.has("voidField")); EXPECT_TRUE(root.has("int32Field")); EXPECT_FALSE(root.has("structField")); EXPECT_FALSE(root.has("int32List")); EXPECT_FALSE(root.has("voidField", HasMode::NON_DEFAULT)); EXPECT_FALSE(root.has("int32Field", HasMode::NON_DEFAULT)); EXPECT_FALSE(root.has("structField", HasMode::NON_DEFAULT)); EXPECT_FALSE(root.has("int32List", HasMode::NON_DEFAULT)); } TEST(DynamicApi, SetEnumFromNative) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.set("enumField", TestEnum::BAZ); root.set("enumList", {TestEnum::BAR, TestEnum::FOO}); EXPECT_EQ(TestEnum::BAZ, root.get("enumField").as()); checkList(root.get("enumList"), {TestEnum::BAR, TestEnum::FOO}); } TEST(DynamicApi, SetDataFromText) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); root.set("dataField", "foo"); EXPECT_EQ(data("foo"), root.get("dataField").as()); } TEST(DynamicApi, BuilderAssign) { MallocMessageBuilder builder; auto root = builder.initRoot(Schema::from()); // Declare upfront, assign later. // Note that the Python implementation requires defaulted constructors. Do not delete them! DynamicValue::Builder value; DynamicStruct::Builder structValue; DynamicList::Builder listValue; value = root.get("structField"); structValue = value.as(); structValue.set("int32Field", 123); value = root.init("int32List", 1); listValue = value.as(); listValue.set(0, 123); } TEST(DynamicApi, SetGroup) { MallocMessageBuilder srcBuilder; MallocMessageBuilder dstBuilder; auto srcRoot = srcBuilder.initRoot(); auto srcGroup = srcRoot.initGroup1(); srcGroup.setFoo(10); srcGroup.initCorge().setPlugh("howdy"); auto dstRoot = dstBuilder.initRoot(Schema::from()); dstRoot.set("group1", srcGroup.asReader()); auto dstGroup = dstRoot.get("group1").as(); EXPECT_EQ(10u, dstGroup.get("foo").as()); EXPECT_ANY_THROW(dstGroup.get("qux")); EXPECT_EQ("howdy", dstGroup.get("corge").as().get("plugh").as()); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize.h0000644000175000017500000002643714712011043020777 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file implements a simple serialization format for Cap'n Proto messages. The format // is as follows: // // * 32-bit little-endian segment count (4 bytes). // * 32-bit little-endian size of each segment (4*(segment count) bytes). // * Padding so that subsequent data is 64-bit-aligned (0 or 4 bytes). (I.e., if there are an even // number of segments, there are 4 bytes of zeros here, otherwise there is no padding.) // * Data from each segment, in order (8*sum(segment sizes) bytes) // // This format has some important properties: // - It is self-delimiting, so multiple messages may be written to a stream without any external // delimiter. // - The total size and position of each segment can be determined by reading only the first part // of the message, allowing lazy and random-access reading of the segment data. // - A message is always at least 8 bytes. // - A single-segment message can be read entirely in two system calls with no buffering. // - A multi-segment message can be read entirely in three system calls with no buffering. // - The format is appropriate for mmap()ing since all data is aligned. #pragma once #include "message.h" #include CAPNP_BEGIN_HEADER namespace capnp { class FlatArrayMessageReader: public MessageReader { // Parses a message from a flat array. Note that it makes sense to use this together with mmap() // for extremely fast parsing. public: FlatArrayMessageReader(kj::ArrayPtr array, ReaderOptions options = ReaderOptions()); // The array must remain valid until the MessageReader is destroyed. kj::ArrayPtr getSegment(uint id) override; const word* getEnd() const { return end; } // Get a pointer just past the end of the message as determined by reading the message header. // This could actually be before the end of the input array. This pointer is useful e.g. if // you know that the input array has extra stuff appended after the message and you want to // get at it. private: // Optimize for single-segment case. kj::ArrayPtr segment0; kj::Array> moreSegments; const word* end; }; kj::ArrayPtr initMessageBuilderFromFlatArrayCopy( kj::ArrayPtr array, MessageBuilder& target, ReaderOptions options = ReaderOptions()); // Convenience function which reads a message using `FlatArrayMessageReader` then copies the // content into the target `MessageBuilder`, verifying that the message structure is valid // (although not necessarily that it matches the desired schema). // // Returns an ArrayPtr containing any words left over in the array after consuming the whole // message. This is useful when reading multiple messages that have been concatenated. See also // FlatArrayMessageReader::getEnd(). // // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.) kj::Array messageToFlatArray(MessageBuilder& builder); // Constructs a flat array containing the entire content of the given message. // // To output the message as bytes, use `.asBytes()` on the returned word array. Keep in mind that // `asBytes()` returns an ArrayPtr, so you have to save the Array as well to prevent it from being // deleted. For example: // // kj::Array words = messageToFlatArray(myMessage); // kj::ArrayPtr bytes = words.asBytes(); // write(fd, bytes.begin(), bytes.size()); kj::Array messageToFlatArray(kj::ArrayPtr> segments); // Version of messageToFlatArray that takes a raw segment array. size_t computeSerializedSizeInWords(MessageBuilder& builder); // Returns the size, in words, that will be needed to serialize the message, including the header. size_t computeSerializedSizeInWords(kj::ArrayPtr> segments); // Version of computeSerializedSizeInWords that takes a raw segment array. size_t expectedSizeInWordsFromPrefix(kj::ArrayPtr messagePrefix); // Given a prefix of a serialized message, try to determine the expected total size of the message, // in words. The returned size is based on the information known so far; it may be an underestimate // if the prefix doesn't contain the full segment table. // // If the returned value is greater than `messagePrefix.size()`, then the message is not yet // complete and the app cannot parse it yet. If the returned value is less than or equal to // `messagePrefix.size()`, then the returned value is the exact total size of the message; any // remaining bytes are part of the next message. // // This function is useful when reading messages from a stream in an asynchronous way, but when // using the full KJ async infrastructure would be too difficult. Each time bytes are received, // use this function to determine if an entire message is ready to be parsed. // ======================================================================================= class InputStreamMessageReader: public MessageReader { // A MessageReader that reads from an abstract kj::InputStream. See also StreamFdMessageReader // for a subclass specific to file descriptors. public: InputStreamMessageReader(kj::InputStream& inputStream, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); ~InputStreamMessageReader() noexcept(false); // implements MessageReader ---------------------------------------- kj::ArrayPtr getSegment(uint id) override; private: kj::InputStream& inputStream; byte* readPos; // Optimize for single-segment case. kj::ArrayPtr segment0; kj::Array> moreSegments; kj::Array ownedSpace; // Only if scratchSpace wasn't big enough. kj::UnwindDetector unwindDetector; }; void readMessageCopy(kj::InputStream& input, MessageBuilder& target, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Convenience function which reads a message using `InputStreamMessageReader` then copies the // content into the target `MessageBuilder`, verifying that the message structure is valid // (although not necessarily that it matches the desired schema). // // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.) void writeMessage(kj::OutputStream& output, MessageBuilder& builder); // Write the message to the given output stream. void writeMessage(kj::OutputStream& output, kj::ArrayPtr> segments); // Write the segment array to the given output stream. // ======================================================================================= // Specializations for reading from / writing to file descriptors. class StreamFdMessageReader: private kj::FdInputStream, public InputStreamMessageReader { // A MessageReader that reads from a stream-based file descriptor. public: StreamFdMessageReader(int fd, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) : FdInputStream(fd), InputStreamMessageReader(*this, options, scratchSpace) {} // Read message from a file descriptor, without taking ownership of the descriptor. StreamFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) : FdInputStream(kj::mv(fd)), InputStreamMessageReader(*this, options, scratchSpace) {} // Read a message from a file descriptor, taking ownership of the descriptor. ~StreamFdMessageReader() noexcept(false); }; void readMessageCopyFromFd(int fd, MessageBuilder& target, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Convenience function which reads a message using `StreamFdMessageReader` then copies the // content into the target `MessageBuilder`, verifying that the message structure is valid // (although not necessarily that it matches the desired schema). // // (Note that it's also possible to initialize a `MessageBuilder` directly without a copy using one // of `MessageBuilder`'s constructors. However, this approach skips the validation step and is not // safe to use on untrusted input. Therefore, we do not provide a convenience method for it.) void writeMessageToFd(int fd, MessageBuilder& builder); // Write the message to the given file descriptor. // // This function throws an exception on any I/O error. If your code is not exception-safe, be sure // you catch this exception at the call site. If throwing an exception is not acceptable, you // can implement your own OutputStream with arbitrary error handling and then use writeMessage(). void writeMessageToFd(int fd, kj::ArrayPtr> segments); // Write the segment array to the given file descriptor. // // This function throws an exception on any I/O error. If your code is not exception-safe, be sure // you catch this exception at the call site. If throwing an exception is not acceptable, you // can implement your own OutputStream with arbitrary error handling and then use writeMessage(). // ======================================================================================= // inline stuff inline kj::Array messageToFlatArray(MessageBuilder& builder) { return messageToFlatArray(builder.getSegmentsForOutput()); } inline size_t computeSerializedSizeInWords(MessageBuilder& builder) { return computeSerializedSizeInWords(builder.getSegmentsForOutput()); } inline void writeMessage(kj::OutputStream& output, MessageBuilder& builder) { writeMessage(output, builder.getSegmentsForOutput()); } inline void writeMessageToFd(int fd, MessageBuilder& builder) { writeMessageToFd(fd, builder.getSegmentsForOutput()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/afl-testcase.c++0000644000175000017500000001131614712011043021472 0ustar00kentonkenton00000000000000// Copyright (c) 2017 Cloudflare, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "test-util.h" #include #include "serialize.h" #include #include namespace capnp { namespace _ { namespace { class AflTestMain { public: explicit AflTestMain(kj::ProcessContext& context) : context(context) {} kj::MainFunc getMain() { return kj::MainBuilder(context, "(unknown version)", "American Fuzzy Lop test case. Pass input on stdin. Expects a binary " "message of type TestAllTypes.") .addOption({"lists"}, KJ_BIND_METHOD(*this, runLists), "Expect a message of type TestLists instead of TestAllTypes.") .addOption({"canonicalize"}, KJ_BIND_METHOD(*this, canonicalize), "Test canonicalization code.") .callAfterParsing(KJ_BIND_METHOD(*this, run)) .build(); } kj::MainBuilder::Validity run() { capnp::StreamFdMessageReader reader(STDIN_FILENO); KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { checkTestMessage(reader.getRoot()); })) { KJ_LOG(ERROR, "threw"); } KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { checkDynamicTestMessage(reader.getRoot(Schema::from())); })) { KJ_LOG(ERROR, "dynamic threw"); } KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { kj::str(reader.getRoot()); })) { KJ_LOG(ERROR, "str threw"); } return true; } kj::MainBuilder::Validity runLists() { capnp::StreamFdMessageReader reader(STDIN_FILENO); KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { kj::str(reader.getRoot()); })) { KJ_LOG(ERROR, "threw"); } return true; } kj::MainBuilder::Validity canonicalize() { // (Test case contributed by David Renshaw.) kj::Array canonical; bool equal = false; KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { capnp::ReaderOptions options; // The default traversal limit of 8 * 1024 * 1024 causes // AFL to think that it has found "hang" bugs. options.traversalLimitInWords = 8 * 1024; capnp::StreamFdMessageReader message(0, options); // read from stdin TestAllTypes::Reader myStruct = message.getRoot(); canonical = capnp::canonicalize(myStruct); kj::ArrayPtr segments[1] = {canonical.asPtr()}; capnp::SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); auto originalAny = message.getRoot(); // Discard cases where the original message is null. KJ_ASSERT(!originalAny.isNull()); equal = originalAny == reader.getRoot(); })) { // Probably some kind of decoding exception. KJ_LOG(ERROR, "threw"); context.exit(); } KJ_ASSERT(equal); kj::ArrayPtr segments[1] = {canonical.asPtr()}; capnp::SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1)); KJ_ASSERT(reader.isCanonical()); kj::Array canonical2; { capnp::ReaderOptions options; options.traversalLimitInWords = 8 * 1024; TestAllTypes::Reader myStruct = reader.getRoot(); canonical2 = capnp::canonicalize(myStruct); } KJ_ASSERT(canonical.size() == canonical2.size()); auto b1 = canonical.asBytes(); auto b2 = canonical2.asBytes(); for (int idx = 0; idx < b1.size(); ++idx) { KJ_ASSERT(b1[idx] == b2[idx], idx, b1.size()); } return true; } private: kj::ProcessContext& context; }; } // namespace } // namespace _ } // namespace capnp KJ_MAIN(capnp::_::AflTestMain); capnproto-c++-1.1.0/src/capnp/rpc-twoparty.c++0000644000175000017500000004576114712011043021605 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "rpc-twoparty.h" #include "serialize-async.h" #include #include namespace capnp { TwoPartyVatNetwork::TwoPartyVatNetwork( kj::OneOf>&& stream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock) : stream(kj::mv(stream)), maxFdsPerMessage(maxFdsPerMessage), side(side), peerVatId(4), receiveOptions(receiveOptions), previousWrite(kj::READY_NOW), clock(clock), currentOutgoingMessageSendTime(clock.now()) { peerVatId.initRoot().setSide( side == rpc::twoparty::Side::CLIENT ? rpc::twoparty::Side::SERVER : rpc::twoparty::Side::CLIENT); auto paf = kj::newPromiseAndFulfiller(); disconnectPromise = paf.promise.fork(); disconnectFulfiller.fulfiller = kj::mv(paf.fulfiller); } TwoPartyVatNetwork::TwoPartyVatNetwork(capnp::MessageStream& stream, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock) : TwoPartyVatNetwork(stream, 0, side, receiveOptions, clock) {} TwoPartyVatNetwork::TwoPartyVatNetwork( capnp::MessageStream& stream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock) : TwoPartyVatNetwork(&stream, maxFdsPerMessage, side, receiveOptions, clock) {} TwoPartyVatNetwork::TwoPartyVatNetwork(kj::AsyncIoStream& stream, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock) : TwoPartyVatNetwork( kj::Own(kj::heap( stream, IncomingRpcMessage::getShortLivedCallback())), 0, side, receiveOptions, clock) {} TwoPartyVatNetwork::TwoPartyVatNetwork(kj::AsyncCapabilityStream& stream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock) : TwoPartyVatNetwork( kj::Own(kj::heap( stream, IncomingRpcMessage::getShortLivedCallback())), maxFdsPerMessage, side, receiveOptions, clock) {} TwoPartyVatNetwork::~TwoPartyVatNetwork() noexcept(false) {}; MessageStream& TwoPartyVatNetwork::getStream() { KJ_SWITCH_ONEOF(stream) { KJ_CASE_ONEOF(s, MessageStream*) { return *s; } KJ_CASE_ONEOF(s, kj::Own) { return *s; } } KJ_UNREACHABLE; } void TwoPartyVatNetwork::FulfillerDisposer::disposeImpl(void* pointer) const { if (--refcount == 0) { fulfiller->fulfill(); } } kj::Own TwoPartyVatNetwork::asConnection() { ++disconnectFulfiller.refcount; return kj::Own(this, disconnectFulfiller); } kj::Maybe> TwoPartyVatNetwork::connect( rpc::twoparty::VatId::Reader ref) { if (ref.getSide() == side) { return nullptr; } else { return asConnection(); } } kj::Promise> TwoPartyVatNetwork::accept() { if (side == rpc::twoparty::Side::SERVER && !accepted) { accepted = true; return asConnection(); } else { // Create a promise that will never be fulfilled. auto paf = kj::newPromiseAndFulfiller>(); acceptFulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } } class TwoPartyVatNetwork::OutgoingMessageImpl final : public OutgoingRpcMessage, public kj::Refcounted { public: OutgoingMessageImpl(TwoPartyVatNetwork& network, uint firstSegmentWordSize) : network(network), message(firstSegmentWordSize == 0 ? SUGGESTED_FIRST_SEGMENT_WORDS : firstSegmentWordSize) {} AnyPointer::Builder getBody() override { return message.getRoot(); } void setFds(kj::Array fds) override { if (network.maxFdsPerMessage > 0) { this->fds = kj::mv(fds); } } void send() override { size_t size = 0; for (auto& segment: message.getSegmentsForOutput()) { size += segment.size(); } KJ_REQUIRE(size < network.receiveOptions.traversalLimitInWords, size, "Trying to send Cap'n Proto message larger than our single-message size limit. The " "other side probably won't accept it (assuming its traversalLimitInWords matches " "ours) and would abort the connection, so I won't send it.") { return; } auto sendTime = network.clock.now(); if (network.queuedMessages.size() == 0) { // Optimistically set sendTime when there's no messages in the queue. Without this, sending // a message after a long delay could cause getOutgoingMessageWaitTime() to return excessively // long wait times if it is called during the time period after send() is called, // but before the write occurs, as we increment currentQueueCount synchronously, but // asynchronously update currentOutgoingMessageSendTime. network.currentOutgoingMessageSendTime = sendTime; } // Instead of sending each new message as soon as possible, we attempt to batch together small // messages by delaying when we send them using evalLast. This allows us to group together // related small messages, reducing the number of syscalls we make. auto& previousWrite = KJ_ASSERT_NONNULL(network.previousWrite, "already shut down"); bool alreadyPendingSend = !network.queuedMessages.empty(); network.currentQueueSize += message.sizeInWords() * sizeof(word); network.queuedMessages.add(kj::addRef(*this)); if (alreadyPendingSend) { // The first send sets up an evalLast that will clear out pendingMessages when it's sent. // If pendingMessages is non-empty, then there must already be a callback waiting to send // them. return; } // On the other hand, if pendingMessages was empty, then we should set up the delayed write. network.previousWrite = previousWrite.then([this, sendTime]() { return kj::evalLast([this, sendTime]() -> kj::Promise { network.currentOutgoingMessageSendTime = sendTime; // Swap out the connection's pending messages and write all of them together. auto ownMessages = kj::mv(network.queuedMessages); network.currentQueueSize = 0; auto messages = kj::heapArray(ownMessages.size()); for (int i = 0; i < messages.size(); ++i) { messages[i].segments = ownMessages[i]->message.getSegmentsForOutput(); messages[i].fds = ownMessages[i]->fds; } return network.getStream().writeMessages(messages).attach(kj::mv(ownMessages), kj::mv(messages)); }).catch_([this](kj::Exception&& e) { // Since no one checks write failures, we need to propagate them into read failures, // otherwise we might get stuck sending all messages into a black hole and wondering why // the peer never replies. network.readCancelReason = kj::cp(e); if (!network.readCanceler.isEmpty()) { network.readCanceler.cancel(kj::cp(e)); } kj::throwRecoverableException(kj::mv(e)); }); }).attach(kj::addRef(*this)) // Note that it's important that the eagerlyEvaluate() come *after* the attach() because // otherwise the message (and any capabilities in it) will not be released until a new // message is written! (Kenton once spent all afternoon tracking this down...) .eagerlyEvaluate(nullptr); } size_t sizeInWords() override { return message.sizeInWords(); } private: TwoPartyVatNetwork& network; MallocMessageBuilder message; kj::Array fds; }; kj::Duration TwoPartyVatNetwork::getOutgoingMessageWaitTime() { if (queuedMessages.size() > 0) { return clock.now() - currentOutgoingMessageSendTime; } else { return 0 * kj::SECONDS; } } class TwoPartyVatNetwork::IncomingMessageImpl final: public IncomingRpcMessage { public: IncomingMessageImpl(kj::Own message): message(kj::mv(message)) {} IncomingMessageImpl(MessageReaderAndFds init, kj::Array fdSpace) : message(kj::mv(init.reader)), fdSpace(kj::mv(fdSpace)), fds(init.fds) { KJ_DASSERT(this->fds.begin() == this->fdSpace.begin()); } AnyPointer::Reader getBody() override { return message->getRoot(); } kj::ArrayPtr getAttachedFds() override { return fds; } size_t sizeInWords() override { return message->sizeInWords(); } private: kj::Own message; kj::Array fdSpace; kj::ArrayPtr fds; }; kj::Own TwoPartyVatNetwork::newStream() { return RpcFlowController::newVariableWindowController(*this); } size_t TwoPartyVatNetwork::getWindow() { // The socket's send buffer size -- as returned by getsockopt(SO_SNDBUF) -- tells us how much // data the kernel itself is willing to buffer. The kernel will increase the send buffer size if // needed to fill the connection's congestion window. So we can cheat and use it as our stream // window, too, to make sure we saturate said congestion window. // // TODO(perf): Unfortunately, this hack breaks down in the presence of proxying. What we really // want is the window all the way to the endpoint, which could cross multiple connections. The // first-hop window could be either too big or too small: it's too big if the first hop has // much higher bandwidth than the full path (causing buffering at the bottleneck), and it's // too small if the first hop has much lower latency than the full path (causing not enough // data to be sent to saturate the connection). To handle this, we could either: // 1. Have proxies be aware of streaming, by flagging streaming calls in the RPC protocol. The // proxies would then handle backpressure at each hop. This seems simple to implement but // requires base RPC protocol changes and might require thinking carefully about e-ordering // implications. Also, it only fixes underutilization; it does not fix buffer bloat. // 2. Do our own BBR-like computation, where the client measures the end-to-end latency and // bandwidth based on the observed sends and returns, and then compute the window based on // that. This seems complicated, but avoids the need for any changes to the RPC protocol. // In theory it solves both underutilization and buffer bloat. Note that this approach would // require the RPC system to use a clock, which feels dirty and adds non-determinism. if (solSndbufUnimplemented) { return RpcFlowController::DEFAULT_WINDOW_SIZE; } else { KJ_IF_MAYBE(bufSize, getStream().getSendBufferSize()) { return *bufSize; } else { solSndbufUnimplemented = true; return RpcFlowController::DEFAULT_WINDOW_SIZE; } } } rpc::twoparty::VatId::Reader TwoPartyVatNetwork::getPeerVatId() { return peerVatId.getRoot(); } kj::Own TwoPartyVatNetwork::newOutgoingMessage(uint firstSegmentWordSize) { return kj::refcounted(*this, firstSegmentWordSize); } kj::Promise>> TwoPartyVatNetwork::receiveIncomingMessage() { return kj::evalLater([this]() -> kj::Promise>> { KJ_IF_MAYBE(e, readCancelReason) { // A previous write failed; propagate the failure to reads, too. return kj::cp(*e); } kj::Array fdSpace = nullptr; if(maxFdsPerMessage > 0) { fdSpace = kj::heapArray(maxFdsPerMessage); } auto promise = readCanceler.wrap(getStream().tryReadMessage(fdSpace, receiveOptions)); return promise.then([fdSpace = kj::mv(fdSpace)] (kj::Maybe&& messageAndFds) mutable -> kj::Maybe> { KJ_IF_MAYBE(m, messageAndFds) { if (m->fds.size() > 0) { return kj::Own( kj::heap(kj::mv(*m), kj::mv(fdSpace))); } else { return kj::Own(kj::heap(kj::mv(m->reader))); } } else { return nullptr; } }); }); } kj::Promise TwoPartyVatNetwork::shutdown() { kj::Promise result = KJ_ASSERT_NONNULL(previousWrite, "already shut down").then([this]() { return getStream().end(); }); previousWrite = nullptr; return kj::mv(result); } // ======================================================================================= TwoPartyServer::TwoPartyServer(Capability::Client bootstrapInterface, kj::Maybe> traceEncoder) : bootstrapInterface(kj::mv(bootstrapInterface)), traceEncoder(kj::mv(traceEncoder)), tasks(*this) {} struct TwoPartyServer::AcceptedConnection { kj::Own connection; TwoPartyVatNetwork network; RpcSystem rpcSystem; explicit AcceptedConnection(TwoPartyServer& parent, kj::Own&& connectionParam) : connection(kj::mv(connectionParam)), network(*connection, rpc::twoparty::Side::SERVER), rpcSystem(makeRpcServer(network, kj::cp(parent.bootstrapInterface))) { init(parent); } explicit AcceptedConnection(TwoPartyServer& parent, kj::Own&& connectionParam, uint maxFdsPerMessage) : connection(kj::mv(connectionParam)), network(kj::downcast(*connection), maxFdsPerMessage, rpc::twoparty::Side::SERVER), rpcSystem(makeRpcServer(network, kj::cp(parent.bootstrapInterface))) { init(parent); } void init(TwoPartyServer& parent) { KJ_IF_MAYBE(t, parent.traceEncoder) { rpcSystem.setTraceEncoder([&func = *t](const kj::Exception& e) { return func(e); }); } } }; void TwoPartyServer::accept(kj::Own&& connection) { auto connectionState = kj::heap(*this, kj::mv(connection)); // Run the connection until disconnect. auto promise = connectionState->network.onDisconnect(); tasks.add(promise.attach(kj::mv(connectionState))); } void TwoPartyServer::accept( kj::Own&& connection, uint maxFdsPerMessage) { auto connectionState = kj::heap( *this, kj::mv(connection), maxFdsPerMessage); // Run the connection until disconnect. auto promise = connectionState->network.onDisconnect(); tasks.add(promise.attach(kj::mv(connectionState))); } kj::Promise TwoPartyServer::accept(kj::AsyncIoStream& connection) { auto connectionState = kj::heap(*this, kj::Own(&connection, kj::NullDisposer::instance)); // Run the connection until disconnect. auto promise = connectionState->network.onDisconnect(); return promise.attach(kj::mv(connectionState)); } kj::Promise TwoPartyServer::accept( kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage) { auto connectionState = kj::heap(*this, kj::Own(&connection, kj::NullDisposer::instance), maxFdsPerMessage); // Run the connection until disconnect. auto promise = connectionState->network.onDisconnect(); return promise.attach(kj::mv(connectionState)); } kj::Promise TwoPartyServer::listen(kj::ConnectionReceiver& listener) { return listener.accept() .then([this,&listener](kj::Own&& connection) mutable { accept(kj::mv(connection)); return listen(listener); }); } kj::Promise TwoPartyServer::listenCapStreamReceiver( kj::ConnectionReceiver& listener, uint maxFdsPerMessage) { return listener.accept() .then([this,&listener,maxFdsPerMessage](kj::Own&& connection) mutable { accept(connection.downcast(), maxFdsPerMessage); return listenCapStreamReceiver(listener, maxFdsPerMessage); }); } void TwoPartyServer::taskFailed(kj::Exception&& exception) { KJ_LOG(ERROR, exception); } TwoPartyClient::TwoPartyClient(kj::AsyncIoStream& connection) : network(connection, rpc::twoparty::Side::CLIENT), rpcSystem(makeRpcClient(network)) {} TwoPartyClient::TwoPartyClient(kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage) : network(connection, maxFdsPerMessage, rpc::twoparty::Side::CLIENT), rpcSystem(makeRpcClient(network)) {} TwoPartyClient::TwoPartyClient(kj::AsyncIoStream& connection, Capability::Client bootstrapInterface, rpc::twoparty::Side side) : network(connection, side), rpcSystem(network, bootstrapInterface) {} TwoPartyClient::TwoPartyClient(kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage, Capability::Client bootstrapInterface, rpc::twoparty::Side side) : network(connection, maxFdsPerMessage, side), rpcSystem(network, bootstrapInterface) {} Capability::Client TwoPartyClient::bootstrap() { capnp::word scratch[4]; memset(&scratch, 0, sizeof(scratch)); capnp::MallocMessageBuilder message(scratch); auto vatId = message.getRoot(); vatId.setSide(network.getSide() == rpc::twoparty::Side::CLIENT ? rpc::twoparty::Side::SERVER : rpc::twoparty::Side::CLIENT); return rpcSystem.bootstrap(vatId); } void TwoPartyClient::setTraceEncoder(kj::Function func) { rpcSystem.setTraceEncoder(kj::mv(func)); } } // namespace capnp capnproto-c++-1.1.0/src/capnp/orphan.h0000644000175000017500000004253714712011043020276 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "layout.h" CAPNP_BEGIN_HEADER namespace capnp { class StructSchema; class ListSchema; struct DynamicStruct; struct DynamicList; namespace _ { struct OrphanageInternal; } template class Orphan { // Represents an object which is allocated within some message builder but has no pointers // pointing at it. An Orphan can later be "adopted" by some other object as one of that object's // fields, without having to copy the orphan. For a field `foo` of pointer type, the generated // code will define builder methods `void adoptFoo(Orphan)` and `Orphan disownFoo()`. // Orphans can also be created independently of any parent using an Orphanage. // // `Orphan` can be moved but not copied, like `Own`, so that it is impossible for one // orphan to be adopted multiple times. If an orphan is destroyed without being adopted, its // contents are zero'd out (and possibly reused, if we ever implement the ability to reuse space // in a message arena). public: Orphan() = default; KJ_DISALLOW_COPY(Orphan); Orphan(Orphan&&) = default; Orphan& operator=(Orphan&&) = default; inline Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {} inline BuilderFor get(); // Get the underlying builder. If the orphan is null, this will allocate and return a default // object rather than crash. This is done for security -- otherwise, you might enable a DoS // attack any time you disown a field and fail to check if it is null. In the case of structs, // this means that the orphan is no longer null after get() returns. In the case of lists, // no actual object is allocated since a simple empty ListBuilder can be returned. inline ReaderFor getReader() const; inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } inline void truncate(uint size); // Resize an object (which must be a list or a blob) to the given size. // // If the new size is less than the original, the remaining elements will be discarded. The // list is never moved in this case. If the list happens to be located at the end of its segment // (which is always true if the list was the last thing allocated), the removed memory will be // reclaimed (reducing the message size), otherwise it is simply zeroed. The reclaiming behavior // is particularly useful for allocating buffer space when you aren't sure how much space you // actually need: you can pre-allocate, say, a 4k byte array, read() from a file into it, and // then truncate it back to the amount of space actually used. // // If the new size is greater than the original, the list is extended with default values. If // the list is the last object in its segment *and* there is enough space left in the segment to // extend it to cover the new values, then the list is extended in-place. Otherwise, it must be // moved to a new location, leaving a zero'd hole in the previous space that won't be filled. // This copy is shallow; sub-objects will simply be reparented, not copied. // // Any existing readers or builders pointing at the object are invalidated by this call (even if // it doesn't move). You must call `get()` or `getReader()` again to get the new, valid pointer. private: _::OrphanBuilder builder; template friend struct _::PointerHelpers; template friend struct List; template friend class Orphan; friend class Orphanage; friend class MessageBuilder; }; class Orphanage: private kj::DisallowConstCopy { // Use to directly allocate Orphan objects, without having a parent object allocate and then // disown the object. public: inline Orphanage(): arena(nullptr) {} template static Orphanage getForMessageContaining(BuilderType builder); // Construct an Orphanage that allocates within the message containing the given Builder. This // allows the constructed Orphans to be adopted by objects within said message. // // This constructor takes the builder rather than having the builder have a getOrphanage() method // because this is an advanced feature and we don't want to pollute the builder APIs with it. // // Note that if you have a direct pointer to the `MessageBuilder`, you can simply call its // `getOrphanage()` method. template Orphan newOrphan() const; // Allocate a new orphaned struct. template Orphan newOrphan(uint size) const; // Allocate a new orphaned list or blob. Orphan newOrphan(StructSchema schema) const; // Dynamically create an orphan struct with the given schema. You must // #include to use this. Orphan newOrphan(ListSchema schema, uint size) const; // Dynamically create an orphan list with the given schema. You must #include // to use this. template Orphan> newOrphanCopy(Reader copyFrom) const; // Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the // given object. template Orphan>>> newOrphanConcat(kj::ArrayPtr lists) const; template Orphan>>> newOrphanConcat(kj::ArrayPtr lists) const; // Given an array of List readers, copy and concatenate the lists, creating a new Orphan. // // Note that compared to allocating the list yourself and using `setWithCaveats()` to set each // item, this method avoids the "caveats": the new list will be allocated with the element size // being the maximum of that from all the input lists. This is particularly important when // concatenating struct lists: if the lists were created using a newer version of the protocol // in which some new fields had been added to the struct, using `setWithCaveats()` would // truncate off those new fields. Orphan referenceExternalData(Data::Reader data) const; // Creates an Orphan that points at an existing region of memory (e.g. from another message) // without copying it. There are some SEVERE restrictions on how this can be used: // - The memory must remain valid until the `MessageBuilder` is destroyed (even if the orphan is // abandoned). // - Because the data is const, you will not be allowed to obtain a `Data::Builder` // for this blob. Any call which would return such a builder will throw an exception. You // can, however, obtain a Reader, e.g. via orphan.getReader() or from a parent Reader (once // the orphan is adopted). It is your responsibility to make sure your code can deal with // these problems when using this optimization; if you can't, allocate a copy instead. // - `data.begin()` must be aligned to a machine word boundary (32-bit or 64-bit depending on // the CPU). Any pointer returned by malloc() as well as any data blob obtained from another // Cap'n Proto message satisfies this. // - If `data.size()` is not a multiple of 8, extra bytes past data.end() up until the next 8-byte // boundary will be visible in the raw message when it is written out. Thus, there must be no // secrets in these bytes. Data blobs obtained from other Cap'n Proto messages should be safe // as these bytes should be zero (unless the sender had the same problem). // // The array will actually become one of the message's segments. The data can thus be adopted // into the message tree without copying it. This is particularly useful when referencing very // large blobs, such as whole mmap'd files. private: _::BuilderArena* arena; _::CapTableBuilder* capTable; inline explicit Orphanage(_::BuilderArena* arena, _::CapTableBuilder* capTable) : arena(arena), capTable(capTable) {} template struct GetInnerBuilder; template struct GetInnerReader; template struct NewOrphanListImpl; friend class MessageBuilder; friend struct _::OrphanageInternal; }; // ======================================================================================= // Inline implementation details. namespace _ { // private template struct OrphanGetImpl; template struct OrphanGetImpl { static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, _::elementSizeForType()); } }; template struct OrphanGetImpl { static inline typename T::Builder apply(_::OrphanBuilder& builder) { return typename T::Builder(builder.asStruct(_::structSize())); } static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) { return typename T::Reader(builder.asStructReader(_::structSize())); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, _::structSize()); } }; #if !CAPNP_LITE template struct OrphanGetImpl { static inline typename T::Client apply(_::OrphanBuilder& builder) { return typename T::Client(builder.asCapability()); } static inline typename T::Client applyReader(const _::OrphanBuilder& builder) { return typename T::Client(builder.asCapability()); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; #endif // !CAPNP_LITE template struct OrphanGetImpl, Kind::LIST> { static inline typename List::Builder apply(_::OrphanBuilder& builder) { return typename List::Builder(builder.asList(_::ElementSizeForType::value)); } static inline typename List::Reader applyReader(const _::OrphanBuilder& builder) { return typename List::Reader(builder.asListReader(_::ElementSizeForType::value)); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; template struct OrphanGetImpl, Kind::LIST> { static inline typename List::Builder apply(_::OrphanBuilder& builder) { return typename List::Builder(builder.asStructList(_::structSize())); } static inline typename List::Reader applyReader(const _::OrphanBuilder& builder) { return typename List::Reader(builder.asListReader(_::ElementSizeForType::value)); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; template <> struct OrphanGetImpl { static inline Text::Builder apply(_::OrphanBuilder& builder) { return Text::Builder(builder.asText()); } static inline Text::Reader applyReader(const _::OrphanBuilder& builder) { return Text::Reader(builder.asTextReader()); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; template <> struct OrphanGetImpl { static inline Data::Builder apply(_::OrphanBuilder& builder) { return Data::Builder(builder.asData()); } static inline Data::Reader applyReader(const _::OrphanBuilder& builder) { return Data::Reader(builder.asDataReader()); } static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) { builder.truncate(size, ElementSize::POINTER); } }; struct OrphanageInternal { static inline _::BuilderArena* getArena(Orphanage orphanage) { return orphanage.arena; } static inline _::CapTableBuilder* getCapTable(Orphanage orphanage) { return orphanage.capTable; } }; } // namespace _ (private) template inline BuilderFor Orphan::get() { return _::OrphanGetImpl::apply(builder); } template inline ReaderFor Orphan::getReader() const { return _::OrphanGetImpl::applyReader(builder); } template inline void Orphan::truncate(uint size) { _::OrphanGetImpl>::truncateListOf(builder, bounded(size) * ELEMENTS); } template <> inline void Orphan::truncate(uint size) { builder.truncateText(bounded(size) * ELEMENTS); } template <> inline void Orphan::truncate(uint size) { builder.truncate(bounded(size) * ELEMENTS, ElementSize::BYTE); } template struct Orphanage::GetInnerBuilder { static inline _::StructBuilder apply(typename T::Builder& t) { return t._builder; } }; template struct Orphanage::GetInnerBuilder { static inline _::ListBuilder apply(typename T::Builder& t) { return t.builder; } }; template Orphanage Orphanage::getForMessageContaining(BuilderType builder) { auto inner = GetInnerBuilder>::apply(builder); return Orphanage(inner.getArena(), inner.getCapTable()); } template Orphan Orphanage::newOrphan() const { return Orphan(_::OrphanBuilder::initStruct(arena, capTable, _::structSize())); } template struct Orphanage::NewOrphanListImpl> { static inline _::OrphanBuilder apply( _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { return _::OrphanBuilder::initList( arena, capTable, bounded(size) * ELEMENTS, _::ElementSizeForType::value); } }; template struct Orphanage::NewOrphanListImpl> { static inline _::OrphanBuilder apply( _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { return _::OrphanBuilder::initStructList( arena, capTable, bounded(size) * ELEMENTS, _::structSize()); } }; template <> struct Orphanage::NewOrphanListImpl { static inline _::OrphanBuilder apply( _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { return _::OrphanBuilder::initText(arena, capTable, bounded(size) * BYTES); } }; template <> struct Orphanage::NewOrphanListImpl { static inline _::OrphanBuilder apply( _::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) { return _::OrphanBuilder::initData(arena, capTable, bounded(size) * BYTES); } }; template Orphan Orphanage::newOrphan(uint size) const { return Orphan(NewOrphanListImpl::apply(arena, capTable, size)); } template struct Orphanage::GetInnerReader { static inline _::StructReader apply(const typename T::Reader& t) { return t._reader; } }; template struct Orphanage::GetInnerReader { static inline _::ListReader apply(const typename T::Reader& t) { return t.reader; } }; template struct Orphanage::GetInnerReader { static inline const typename T::Reader& apply(const typename T::Reader& t) { return t; } }; template inline Orphan> Orphanage::newOrphanCopy(Reader copyFrom) const { return Orphan>(_::OrphanBuilder::copy( arena, capTable, GetInnerReader>::apply(copyFrom))); } template inline Orphan>>> Orphanage::newOrphanConcat(kj::ArrayPtr lists) const { return newOrphanConcat(kj::implicitCast>(lists)); } template inline Orphan>>> Orphanage::newOrphanConcat(kj::ArrayPtr lists) const { // Optimization / simplification: Rely on List::Reader containing nothing except a // _::ListReader. static_assert(sizeof(T) == sizeof(_::ListReader), "lists are not bare readers?"); kj::ArrayPtr raw( reinterpret_cast(lists.begin()), lists.size()); typedef ListElementType> Element; return Orphan>( _::OrphanBuilder::concat(arena, capTable, _::elementSizeForType(), _::minStructSizeForElement(), raw)); } inline Orphan Orphanage::referenceExternalData(Data::Reader data) const { return Orphan(_::OrphanBuilder::referenceExternalData(arena, data)); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/serialize-async-test.c++0000644000175000017500000004173314712011043023204 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #if _WIN32 #include #endif #include "serialize-async.h" #include "serialize.h" #include #include #include #include #include "test-util.h" #include #include #if _WIN32 #include #include namespace kj { namespace _ { int win32Socketpair(SOCKET socks[2]); } } #else #include #endif namespace capnp { namespace _ { // private namespace { #if _WIN32 inline void delay() { Sleep(5); } #else inline void delay() { usleep(5000); } #endif class FragmentingOutputStream: public kj::OutputStream { public: FragmentingOutputStream(kj::OutputStream& inner): inner(inner) {} void write(const void* buffer, size_t size) override { while (size > 0) { delay(); size_t n = rand() % size + 1; inner.write(buffer, n); buffer = reinterpret_cast(buffer) + n; size -= n; } } private: kj::OutputStream& inner; }; class TestMessageBuilder: public MallocMessageBuilder { // A MessageBuilder that tries to allocate an exact number of total segments, by allocating // minimum-size segments until it reaches the number, then allocating one large segment to // finish. public: explicit TestMessageBuilder(uint desiredSegmentCount) : MallocMessageBuilder(0, AllocationStrategy::FIXED_SIZE), desiredSegmentCount(desiredSegmentCount) {} ~TestMessageBuilder() { EXPECT_EQ(0u, desiredSegmentCount); } kj::ArrayPtr allocateSegment(uint minimumSize) override { if (desiredSegmentCount <= 1) { if (desiredSegmentCount < 1) { ADD_FAILURE() << "Allocated more segments than desired."; } else { --desiredSegmentCount; } return MallocMessageBuilder::allocateSegment(8192); } else { --desiredSegmentCount; return MallocMessageBuilder::allocateSegment(minimumSize); } } private: uint desiredSegmentCount; }; class PipeWithSmallBuffer { public: #ifdef _WIN32 #define KJ_SOCKCALL KJ_WINSOCK #ifndef SHUT_WR #define SHUT_WR SD_SEND #endif #define socketpair(family, type, flags, fds) kj::_::win32Socketpair(fds) #else #define KJ_SOCKCALL KJ_SYSCALL #endif PipeWithSmallBuffer() { // Use a socketpair rather than a pipe so that we can set the buffer size extremely small. KJ_SOCKCALL(socketpair(AF_UNIX, SOCK_STREAM, 0, fds)); KJ_SOCKCALL(shutdown(fds[0], SHUT_WR)); // Note: OSX reports ENOTCONN if we also try to shutdown(fds[1], SHUT_RD). // Request that the buffer size be as small as possible, to force the event loop to kick in. // FUN STUFF: // - On Linux, the kernel rounds up to the smallest size it permits, so we can ask for a size of // zero. // - On OSX, the kernel reports EINVAL on zero, but will dutifully use a 1-byte buffer if we // set the size to 1. This tends to cause stack overflows due to ridiculously long promise // chains. // - Cygwin will apparently actually use a buffer size of 0 and therefore block forever waiting // for buffer space. // - GNU HURD throws ENOPROTOOPT for SO_RCVBUF. Apparently, technically, a Unix domain socket // has only one buffer, and it's controlled via SO_SNDBUF on the other end. OK, we'll ignore // errors on SO_RCVBUF, then. // // Anyway, we now use 127 to avoid these issues (but also to screw around with non-word-boundary // writes). uint small = 127; setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (const char*)&small, sizeof(small)); KJ_SOCKCALL(setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (const char*)&small, sizeof(small))); } ~PipeWithSmallBuffer() { #if _WIN32 closesocket(fds[0]); closesocket(fds[1]); #else close(fds[0]); close(fds[1]); #endif } inline int operator[](uint index) { return fds[index]; } private: #ifdef _WIN32 SOCKET fds[2]; #else int fds[2]; #endif }; #if _WIN32 // Sockets on win32 are not file descriptors. Ugh. // // TODO(cleanup): Maybe put these somewhere reusable? kj/io.h is inappropriate since we don't // really want to link against winsock. class SocketOutputStream: public kj::OutputStream { public: explicit SocketOutputStream(SOCKET fd): fd(fd) {} void write(const void* buffer, size_t size) override { const char* ptr = reinterpret_cast(buffer); while (size > 0) { kj::miniposix::ssize_t n; KJ_SOCKCALL(n = send(fd, ptr, size, 0)); size -= n; ptr += n; } } private: SOCKET fd; }; class SocketInputStream: public kj::InputStream { public: explicit SocketInputStream(SOCKET fd): fd(fd) {} size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override { char* ptr = reinterpret_cast(buffer); size_t total = 0; while (total < minBytes) { kj::miniposix::ssize_t n; KJ_SOCKCALL(n = recv(fd, ptr, maxBytes, 0)); total += n; maxBytes -= n; ptr += n; } return total; } private: SOCKET fd; }; #else // _WIN32 typedef kj::FdOutputStream SocketOutputStream; typedef kj::FdInputStream SocketInputStream; #endif // _WIN32, else TEST(SerializeAsyncTest, ParseAsync) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto input = ioContext.lowLevelProvider->wrapInputFd(fds[0]); SocketOutputStream rawOutput(fds[1]); FragmentingOutputStream output(rawOutput); TestMessageBuilder message(1); initTestMessage(message.getRoot()); kj::Thread thread([&]() { writeMessage(output, message); }); auto received = readMessage(*input).wait(ioContext.waitScope); checkTestMessage(received->getRoot()); } TEST(SerializeAsyncTest, ParseAsyncOddSegmentCount) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto input = ioContext.lowLevelProvider->wrapInputFd(fds[0]); SocketOutputStream rawOutput(fds[1]); FragmentingOutputStream output(rawOutput); TestMessageBuilder message(7); initTestMessage(message.getRoot()); kj::Thread thread([&]() { writeMessage(output, message); }); auto received = readMessage(*input).wait(ioContext.waitScope); checkTestMessage(received->getRoot()); } TEST(SerializeAsyncTest, ParseAsyncEvenSegmentCount) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto input = ioContext.lowLevelProvider->wrapInputFd(fds[0]); SocketOutputStream rawOutput(fds[1]); FragmentingOutputStream output(rawOutput); TestMessageBuilder message(10); initTestMessage(message.getRoot()); kj::Thread thread([&]() { writeMessage(output, message); }); auto received = readMessage(*input).wait(ioContext.waitScope); checkTestMessage(received->getRoot()); } TEST(SerializeAsyncTest, WriteAsync) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto output = ioContext.lowLevelProvider->wrapOutputFd(fds[1]); TestMessageBuilder message(1); auto root = message.getRoot(); auto list = root.initStructList(16); for (auto element: list) { initTestMessage(element); } kj::Thread thread([&]() { SocketInputStream input(fds[0]); InputStreamMessageReader reader(input); auto listReader = reader.getRoot().getStructList(); EXPECT_EQ(list.size(), listReader.size()); for (auto element: listReader) { checkTestMessage(element); } }); writeMessage(*output, message).wait(ioContext.waitScope); } TEST(SerializeAsyncTest, WriteAsyncOddSegmentCount) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto output = ioContext.lowLevelProvider->wrapOutputFd(fds[1]); TestMessageBuilder message(7); auto root = message.getRoot(); auto list = root.initStructList(16); for (auto element: list) { initTestMessage(element); } kj::Thread thread([&]() { SocketInputStream input(fds[0]); InputStreamMessageReader reader(input); auto listReader = reader.getRoot().getStructList(); EXPECT_EQ(list.size(), listReader.size()); for (auto element: listReader) { checkTestMessage(element); } }); writeMessage(*output, message).wait(ioContext.waitScope); } TEST(SerializeAsyncTest, WriteAsyncEvenSegmentCount) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto output = ioContext.lowLevelProvider->wrapOutputFd(fds[1]); TestMessageBuilder message(10); auto root = message.getRoot(); auto list = root.initStructList(16); for (auto element: list) { initTestMessage(element); } kj::Thread thread([&]() { SocketInputStream input(fds[0]); InputStreamMessageReader reader(input); auto listReader = reader.getRoot().getStructList(); EXPECT_EQ(list.size(), listReader.size()); for (auto element: listReader) { checkTestMessage(element); } }); writeMessage(*output, message).wait(ioContext.waitScope); } TEST(SerializeAsyncTest, WriteMultipleMessagesAsync) { PipeWithSmallBuffer fds; auto ioContext = kj::setupAsyncIo(); auto output = ioContext.lowLevelProvider->wrapOutputFd(fds[1]); const int numMessages = 5; const int baseListSize = 16; auto messages = kj::heapArrayBuilder(numMessages); for (int i = 0; i < numMessages; ++i) { messages.add(i+1); auto root = messages[i].getRoot(); auto list = root.initStructList(baseListSize+i); for (auto element: list) { initTestMessage(element); } } kj::Thread thread([&]() { SocketInputStream input(fds[0]); for (int i = 0; i < numMessages; ++i) { InputStreamMessageReader reader(input); auto listReader = reader.getRoot().getStructList(); EXPECT_EQ(baseListSize+i, listReader.size()); for (auto element: listReader) { checkTestMessage(element); } } }); auto msgs = kj::heapArray(numMessages); for (int i = 0; i < numMessages; ++i) { msgs[i] = &messages[i]; } writeMessages(*output, msgs).wait(ioContext.waitScope); } void writeSmallMessage(kj::OutputStream& output, kj::StringPtr text) { capnp::MallocMessageBuilder message; message.getRoot().getAnyPointerField().setAs(text); writeMessage(output, message); } void expectSmallMessage(MessageStream& stream, kj::StringPtr text, kj::WaitScope& waitScope) { auto msg = stream.readMessage().wait(waitScope); KJ_EXPECT(msg->getRoot().getAnyPointerField().getAs() == text); } void writeBigMessage(kj::OutputStream& output) { capnp::MallocMessageBuilder message(4); // first segment is small initTestMessage(message.getRoot()); writeMessage(output, message); } void expectBigMessage(MessageStream& stream, kj::WaitScope& waitScope) { auto msg = stream.readMessage().wait(waitScope); checkTestMessage(msg->getRoot()); } KJ_TEST("BufferedMessageStream basics") { // Encode input data. kj::VectorOutputStream data; writeSmallMessage(data, "foo"); KJ_EXPECT(data.getArray().size() / sizeof(word) == 4); // A big message (more than half a buffer) writeBigMessage(data); KJ_EXPECT(data.getArray().size() / sizeof(word) > 16); writeSmallMessage(data, "bar"); writeSmallMessage(data, "baz"); writeSmallMessage(data, "qux"); // Run the test. kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); auto writePromise = pipe.ends[1]->write(data.getArray().begin(), data.getArray().size()); uint callbackCallCount = 0; auto callback = [&](MessageReader& reader) { ++callbackCallCount; return false; }; BufferedMessageStream stream(*pipe.ends[0], callback, 16); expectSmallMessage(stream, "foo", waitScope); KJ_EXPECT(callbackCallCount == 1); KJ_EXPECT(!writePromise.poll(waitScope)); expectBigMessage(stream, waitScope); KJ_EXPECT(callbackCallCount == 1); // no callback on big message KJ_EXPECT(!writePromise.poll(waitScope)); expectSmallMessage(stream, "bar", waitScope); KJ_EXPECT(callbackCallCount == 2); // All data is now in the buffer, so this part is done. KJ_EXPECT(writePromise.poll(waitScope)); expectSmallMessage(stream, "baz", waitScope); expectSmallMessage(stream, "qux", waitScope); KJ_EXPECT(callbackCallCount == 4); auto eofPromise = stream.MessageStream::tryReadMessage(); KJ_EXPECT(!eofPromise.poll(waitScope)); pipe.ends[1]->shutdownWrite(); KJ_EXPECT(eofPromise.wait(waitScope) == nullptr); } KJ_TEST("BufferedMessageStream fragmented reads") { // Encode input data. kj::VectorOutputStream data; writeBigMessage(data); // Run the test. kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); auto callback = [&](MessageReader& reader) { return false; }; BufferedMessageStream stream(*pipe.ends[0], callback, 16); // Arrange to read a big message. auto readPromise = stream.MessageStream::tryReadMessage(); KJ_EXPECT(!readPromise.poll(waitScope)); auto remainingData = data.getArray(); // Write 5 bytes. This won't even fulfill the first read's minBytes. pipe.ends[1]->write(remainingData.begin(), 5).wait(waitScope); remainingData = remainingData.slice(5, remainingData.size()); KJ_EXPECT(!readPromise.poll(waitScope)); // Write 4 more. Now the MessageStream will only see the first word which contains the first // segment size. This size is small so the MessageStream won't yet fall back to // readEntireMessage(). pipe.ends[1]->write(remainingData.begin(), 4).wait(waitScope); remainingData = remainingData.slice(4, remainingData.size()); KJ_EXPECT(!readPromise.poll(waitScope)); // Drip 10 more bytes. Now the MessageStream will realize that it needs to try // readEntireMessage(). pipe.ends[1]->write(remainingData.begin(), 10).wait(waitScope); remainingData = remainingData.slice(10, remainingData.size()); KJ_EXPECT(!readPromise.poll(waitScope)); // Give it all except the last byte. pipe.ends[1]->write(remainingData.begin(), remainingData.size() - 1).wait(waitScope); remainingData = remainingData.slice(remainingData.size() - 1, remainingData.size()); KJ_EXPECT(!readPromise.poll(waitScope)); // Finish it off. pipe.ends[1]->write(remainingData.begin(), 1).wait(waitScope); KJ_ASSERT(readPromise.poll(waitScope)); auto msg = readPromise.wait(waitScope); checkTestMessage(KJ_ASSERT_NONNULL(msg)->getRoot()); } KJ_TEST("BufferedMessageStream many small messages") { // Encode input data. kj::VectorOutputStream data; for (auto i: kj::zeroTo(16)) { // Intentionally make these 5 words each so they cross buffer boundaries. writeSmallMessage(data, kj::str("12345678-", i)); KJ_EXPECT(data.getArray().size() / sizeof(word) == (i+1) * 5); } // Run the test. kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); auto writePromise = pipe.ends[1]->write(data.getArray().begin(), data.getArray().size()) .then([&]() { // Write some garbage at the end. return pipe.ends[1]->write("bogus", 5); }).then([&]() { // EOF. return pipe.ends[1]->shutdownWrite(); }).eagerlyEvaluate(nullptr); uint callbackCallCount = 0; auto callback = [&](MessageReader& reader) { ++callbackCallCount; return false; }; BufferedMessageStream stream(*pipe.ends[0], callback, 16); for (auto i: kj::zeroTo(16)) { // Intentionally make these 5 words each so they cross buffer boundaries. expectSmallMessage(stream, kj::str("12345678-", i), waitScope); KJ_EXPECT(callbackCallCount == i + 1); } KJ_EXPECT_THROW(DISCONNECTED, stream.MessageStream::tryReadMessage().wait(waitScope)); KJ_EXPECT(callbackCallCount == 16); } // TODO(test): We should probably test BufferedMessageStream's FD handling here... but really it // gets tested well enough by rpc-twoparty-test. } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/generated-header-support.h0000644000175000017500000003331714712011043023701 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file is included from all generated headers. #pragma once #include "raw-schema.h" #include "layout.h" #include "list.h" #include "orphan.h" #include "pointer-helpers.h" #include "any.h" #include #include #include CAPNP_BEGIN_HEADER namespace capnp { class MessageBuilder; // So that it can be declared a friend. template struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend. struct DynamicStruct; // So that it can be declared a friend. struct Capability; // To declare brandBindingFor() namespace _ { // private #if !CAPNP_LITE template inline const RawSchema& rawSchema() { return *CapnpPrivate::schema; } template ::typeId> inline const RawSchema& rawSchema() { return *schemas::EnumInfo::schema; } template inline const RawBrandedSchema& rawBrandedSchema() { return *CapnpPrivate::brand(); } template ::typeId> inline const RawBrandedSchema& rawBrandedSchema() { return schemas::EnumInfo::schema->defaultBrand; } template struct ChooseBrand; // If all of `Params` are `AnyPointer`, return the type's default brand. Otherwise, return a // specific brand instance. TypeTag is the _capnpPrivate struct for the type in question. template struct ChooseBrand { // All params were AnyPointer. No specific brand needed. static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::schema->defaultBrand; } }; template struct ChooseBrand: public ChooseBrand {}; // The first parameter is AnyPointer, so recurse to check the rest. template struct ChooseBrand { // At least one parameter is not AnyPointer, so use the specificBrand constant. static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::specificBrand; } }; template ()> struct BrandBindingFor_; #define HANDLE_TYPE(Type, which) \ template <> \ struct BrandBindingFor_ { \ static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { \ return { which, listDepth, nullptr }; \ } \ } HANDLE_TYPE(Void, 0); HANDLE_TYPE(bool, 1); HANDLE_TYPE(int8_t, 2); HANDLE_TYPE(int16_t, 3); HANDLE_TYPE(int32_t, 4); HANDLE_TYPE(int64_t, 5); HANDLE_TYPE(uint8_t, 6); HANDLE_TYPE(uint16_t, 7); HANDLE_TYPE(uint32_t, 8); HANDLE_TYPE(uint64_t, 9); HANDLE_TYPE(float, 10); HANDLE_TYPE(double, 11); #undef HANDLE_TYPE template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 12, listDepth, nullptr }; } }; template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 13, listDepth, nullptr }; } }; template struct BrandBindingFor_, Kind::LIST> { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return BrandBindingFor_::get(listDepth + 1); } }; template struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 15, listDepth, &rawSchema().defaultBrand }; } }; template struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 16, listDepth, T::_capnpPrivate::brand() }; } }; template struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 17, listDepth, T::_capnpPrivate::brand() }; } }; template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 18, listDepth, 0, 0 }; } }; template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 18, listDepth, 0, 1 }; } }; template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 18, listDepth, 0, 2 }; } }; template <> struct BrandBindingFor_ { static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { return { 18, listDepth, 0, 3 }; } }; template constexpr RawBrandedSchema::Binding brandBindingFor() { return BrandBindingFor_::get(0); } kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema); kj::String enumString(uint16_t value, const RawBrandedSchema& schema); // Declared here so that we can declare inline stringify methods on generated types. // Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in. template inline kj::StringTree structString(StructReader reader) { return structString(reader, rawBrandedSchema()); } template inline kj::String enumString(T value) { return enumString(static_cast(value), rawBrandedSchema()); } #endif // !CAPNP_LITE // TODO(cleanup): Unify ConstStruct and ConstList. template class ConstStruct { public: ConstStruct() = delete; KJ_DISALLOW_COPY_AND_MOVE(ConstStruct); inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {} inline typename T::Reader get() const { return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs(); } inline operator typename T::Reader() const { return get(); } inline typename T::Reader operator*() const { return get(); } inline TemporaryPointer operator->() const { return get(); } private: const word* ptr; }; template class ConstList { public: ConstList() = delete; KJ_DISALLOW_COPY_AND_MOVE(ConstList); inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {} inline typename List::Reader get() const { return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs>(); } inline operator typename List::Reader() const { return get(); } inline typename List::Reader operator*() const { return get(); } inline TemporaryPointer::Reader> operator->() const { return get(); } private: const word* ptr; }; template class ConstText { public: ConstText() = delete; KJ_DISALLOW_COPY_AND_MOVE(ConstText); inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {} inline Text::Reader get() const { return Text::Reader(reinterpret_cast(ptr), size); } inline operator Text::Reader() const { return get(); } inline Text::Reader operator*() const { return get(); } inline TemporaryPointer operator->() const { return get(); } inline kj::StringPtr toString() const { return get(); } private: const word* ptr; }; template inline kj::StringPtr KJ_STRINGIFY(const ConstText& s) { return s.get(); } template class ConstData { public: ConstData() = delete; KJ_DISALLOW_COPY_AND_MOVE(ConstData); inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {} inline Data::Reader get() const { return Data::Reader(reinterpret_cast(ptr), size); } inline operator Data::Reader() const { return get(); } inline Data::Reader operator*() const { return get(); } inline TemporaryPointer operator->() const { return get(); } private: const word* ptr; }; template inline auto KJ_STRINGIFY(const ConstData& s) -> decltype(kj::toCharSequence(s.get())) { return kj::toCharSequence(s.get()); } } // namespace _ (private) template inline constexpr uint64_t typeId() { return CapnpPrivate::typeId; } template ::typeId> inline constexpr uint64_t typeId() { return id; } // typeId() returns the type ID as defined in the schema. Works with structs, enums, and // interfaces. template inline constexpr uint sizeInWords() { // Return the size, in words, of a Struct type, if allocated free-standing (not in a list). // May be useful for pre-computing space needed in order to precisely allocate messages. return unbound((upgradeBound(_::structSize().data) + _::structSize().pointers * WORDS_PER_POINTER) / WORDS); } } // namespace capnp #if _MSC_VER && !defined(__clang__) // MSVC doesn't understand floating-point constexpr yet. // // TODO(msvc): Remove this hack when MSVC is fixed. #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) = value #else #define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) = value #define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) #endif #if _MSC_VER && !defined(__clang__) // TODO(msvc): A little hack to allow MSVC to use C++14 return type deduction in cases where the // explicit type exposes bugs in the compiler. #define CAPNP_AUTO_IF_MSVC(...) auto #else #define CAPNP_AUTO_IF_MSVC(...) __VA_ARGS__ #endif // TODO(msvc): MSVC does not even expect constexprs to have definitions below C++17. #if (KJ_CPP_STD < 201703L) && !(defined(_MSC_VER) && !defined(__clang__)) #define CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL 1 #else #define CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL 0 #endif #if CAPNP_LITE #define CAPNP_DECLARE_SCHEMA(id) \ extern ::capnp::word const* const bp_##id #define CAPNP_DECLARE_ENUM(type, id) \ inline ::kj::String KJ_STRINGIFY(type##_##id value) { \ return ::kj::str(static_cast(value)); \ } \ template <> struct EnumInfo { \ struct IsEnum; \ static constexpr uint64_t typeId = 0x##id; \ static inline ::capnp::word const* encodedSchema() { return bp_##id; } \ } #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #define CAPNP_DEFINE_ENUM(type, id) \ constexpr uint64_t EnumInfo::typeId #else #define CAPNP_DEFINE_ENUM(type, id) #endif #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ struct IsStruct; \ static constexpr uint64_t typeId = 0x##id; \ static constexpr uint16_t dataWordSize = dataWordSize_; \ static constexpr uint16_t pointerCount = pointerCount_; \ static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } #else // CAPNP_LITE #define CAPNP_DECLARE_SCHEMA(id) \ extern ::capnp::word const* const bp_##id; \ extern const ::capnp::_::RawSchema s_##id #define CAPNP_DECLARE_ENUM(type, id) \ inline ::kj::String KJ_STRINGIFY(type##_##id value) { \ return ::capnp::_::enumString(value); \ } \ template <> struct EnumInfo { \ struct IsEnum; \ static constexpr uint64_t typeId = 0x##id; \ static inline ::capnp::word const* encodedSchema() { return bp_##id; } \ static constexpr ::capnp::_::RawSchema const* schema = &s_##id; \ } #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #define CAPNP_DEFINE_ENUM(type, id) \ constexpr uint64_t EnumInfo::typeId; \ constexpr ::capnp::_::RawSchema const* EnumInfo::schema #else #define CAPNP_DEFINE_ENUM(type, id) #endif #define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \ struct IsStruct; \ static constexpr uint64_t typeId = 0x##id; \ static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; \ static constexpr uint16_t dataWordSize = dataWordSize_; \ static constexpr uint16_t pointerCount = pointerCount_; \ static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \ static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; #define CAPNP_DECLARE_INTERFACE_HEADER(id) \ struct IsInterface; \ static constexpr uint64_t typeId = 0x##id; \ static constexpr ::capnp::Kind kind = ::capnp::Kind::INTERFACE; \ static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \ static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id; #endif // CAPNP_LITE, else namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(995f9a3377c0b16e); // HACK: Forward-declare the RawSchema for StreamResult, from stream.capnp. This allows capnp // files which declare streaming methods to avoid including stream.capnp.h. } } CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/persistent.capnp0000644000175000017500000001617014527152321022064 0ustar00kentonkenton00000000000000# Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xb8630836983feed7; $import "/capnp/c++.capnp".namespace("capnp"); interface Persistent@0xc8cb212fcd9f5691(SturdyRef, Owner) { # Interface implemented by capabilities that outlive a single connection. A client may save() # the capability, producing a SturdyRef. The SturdyRef can be stored to disk, then later used to # obtain a new reference to the capability on a future connection. # # The exact format of SturdyRef depends on the "realm" in which the SturdyRef appears. A "realm" # is an abstract space in which all SturdyRefs have the same format and refer to the same set of # resources. Every vat is in exactly one realm. All capability clients within that vat must # produce SturdyRefs of the format appropriate for the realm. # # Similarly, every VatNetwork also resides in a particular realm. Usually, a vat's "realm" # corresponds to the realm of its main VatNetwork. However, a Vat can in fact communicate over # a VatNetwork in a different realm -- in this case, all SturdyRefs need to be transformed when # coming or going through said VatNetwork. The RPC system has hooks for registering # transformation callbacks for this purpose. # # Since the format of SturdyRef is realm-dependent, it is not defined here. An application should # choose an appropriate realm for itself as part of its design. Note that under Sandstorm, every # application exists in its own realm and is therefore free to define its own SturdyRef format; # the Sandstorm platform handles translating between realms. # # Note that whether a capability is persistent is often orthogonal to its type. In these cases, # the capability's interface should NOT inherit `Persistent`; instead, just perform a cast at # runtime. It's not type-safe, but trying to be type-safe in these cases will likely lead to # tears. In cases where a particular interface only makes sense on persistent capabilities, it # still should not explicitly inherit Persistent because the `SturdyRef` and `Owner` types will # vary between realms (they may even be different at the call site than they are on the # implementation). Instead, mark persistent interfaces with the $persistent annotation (defined # below). # # Sealing # ------- # # As an added security measure, SturdyRefs may be "sealed" to a particular owner, such that # if the SturdyRef itself leaks to a third party, that party cannot actually restore it because # they are not the owner. To restore a sealed capability, you must first prove to its host that # you are the rightful owner. The precise mechanism for this authentication is defined by the # realm. # # Sealing is a defense-in-depth mechanism meant to mitigate damage in the case of catastrophic # attacks. For example, say an attacker temporarily gains read access to a database full of # SturdyRefs: it would be unfortunate if it were then necessary to revoke every single reference # in the database to prevent the attacker from using them. # # In general, an "owner" is a course-grained identity. Because capability-based security is still # the primary mechanism of security, it is not necessary nor desirable to have a separate "owner" # identity for every single process or object; that is exactly what capabilities are supposed to # avoid! Instead, it makes sense for an "owner" to literally identify the owner of the machines # where the capability is stored. If untrusted third parties are able to run arbitrary code on # said machines, then the sandbox for that code should be designed using Distributed Confinement # such that the third-party code never sees the bits of the SturdyRefs and cannot directly # exercise the owner's power to restore refs. See: # # http://www.erights.org/elib/capability/dist-confine.html # # Resist the urge to represent an Owner as a simple public key. The whole point of sealing is to # defend against leaked-storage attacks. Such attacks can easily result in the owner's private # key being stolen as well. A better solution is for `Owner` to contain a simple globally unique # identifier for the owner, and for everyone to separately maintain a mapping of owner IDs to # public keys. If an owner's private key is compromised, then humans will need to communicate # and agree on a replacement public key, then update the mapping. # # As a concrete example, an `Owner` could simply contain a domain name, and restoring a SturdyRef # would require signing a request using the domain's private key. Authenticating this key could # be accomplished through certificate authorities or web-of-trust techniques. save @0 SaveParams -> SaveResults; # Save a capability persistently so that it can be restored by a future connection. Not all # capabilities can be saved -- application interfaces should define which capabilities support # this and which do not. struct SaveParams { sealFor @0 :Owner; # Seal the SturdyRef so that it can only be restored by the specified Owner. This is meant # to mitigate damage when a SturdyRef is leaked. See comments above. # # Leaving this value null may or may not be allowed; it is up to the realm to decide. If a # realm does allow a null owner, this should indicate that anyone is allowed to restore the # ref. } struct SaveResults { sturdyRef @0 :SturdyRef; } } annotation persistent(interface, field) :Void; # Apply this annotation to interfaces for objects that will always be persistent, instead of # extending the Persistent capability, since the correct type parameters to Persistent depend on # the realm, which is orthogonal to the interface type and therefore should not be defined # along-side it. # # You may also apply this annotation to a capability-typed field which will always contain a # persistent capability, but where the capability's interface itself is not already marked # persistent. # # Note that absence of the $persistent annotation doesn't mean a capability of that type isn't # persistent; it just means not *all* such capabilities are persistent. capnproto-c++-1.1.0/src/capnp/test-util.c++0000644000175000017500000013737514712011043021067 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "test-util.h" #include #include #include #include namespace capnp { namespace _ { // private namespace { template void genericInitTestMessage(Builder builder) { builder.setVoidField(VOID); builder.setVoidField(); // Means the same as above. builder.setBoolField(true); builder.setInt8Field(-123); builder.setInt16Field(-12345); builder.setInt32Field(-12345678); builder.setInt64Field(-123456789012345ll); builder.setUInt8Field(234u); builder.setUInt16Field(45678u); builder.setUInt32Field(3456789012u); builder.setUInt64Field(12345678901234567890ull); builder.setFloat32Field(1234.5); builder.setFloat64Field(-123e45); builder.setTextField("foo"); builder.setDataField(data("bar")); { auto subBuilder = builder.initStructField(); subBuilder.setVoidField(VOID); subBuilder.setBoolField(true); subBuilder.setInt8Field(-12); subBuilder.setInt16Field(3456); subBuilder.setInt32Field(-78901234); subBuilder.setInt64Field(56789012345678ll); subBuilder.setUInt8Field(90u); subBuilder.setUInt16Field(1234u); subBuilder.setUInt32Field(56789012u); subBuilder.setUInt64Field(345678901234567890ull); subBuilder.setFloat32Field(-1.25e-10f); subBuilder.setFloat64Field(345); subBuilder.setTextField("baz"); subBuilder.setDataField(data("qux")); { auto subSubBuilder = subBuilder.initStructField(); subSubBuilder.setTextField("nested"); subSubBuilder.initStructField().setTextField("really nested"); } subBuilder.setEnumField(TestEnum::BAZ); subBuilder.setVoidList({VOID, VOID, VOID}); subBuilder.setBoolList({false, true, false, true, true}); subBuilder.setInt8List({12, -34, -0x80, 0x7f}); subBuilder.setInt16List({1234, -5678, -0x8000, 0x7fff}); // gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1. subBuilder.setInt32List({12345678, -90123456, -0x7fffffff - 1, 0x7fffffff}); subBuilder.setInt64List({123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll}); subBuilder.setUInt8List({12u, 34u, 0u, 0xffu}); subBuilder.setUInt16List({1234u, 5678u, 0u, 0xffffu}); subBuilder.setUInt32List({12345678u, 90123456u, 0u, 0xffffffffu}); subBuilder.setUInt64List({123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull}); subBuilder.setFloat32List({0, 1234567, 1e37f, -1e37f, 1e-37f, -1e-37f}); subBuilder.setFloat64List({0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306}); subBuilder.setTextList({"quux", "corge", "grault"}); subBuilder.setDataList({data("garply"), data("waldo"), data("fred")}); { auto listBuilder = subBuilder.initStructList(3); listBuilder[0].setTextField("x structlist 1"); listBuilder[1].setTextField("x structlist 2"); listBuilder[2].setTextField("x structlist 3"); } subBuilder.setEnumList({TestEnum::QUX, TestEnum::BAR, TestEnum::GRAULT}); } builder.setEnumField(TestEnum::CORGE); builder.initVoidList(6); builder.setBoolList({true, false, false, true}); builder.setInt8List({111, -111}); builder.setInt16List({11111, -11111}); builder.setInt32List({111111111, -111111111}); builder.setInt64List({1111111111111111111ll, -1111111111111111111ll}); builder.setUInt8List({111u, 222u}); builder.setUInt16List({33333u, 44444u}); builder.setUInt32List({3333333333u}); builder.setUInt64List({11111111111111111111ull}); builder.setFloat32List({5555.5, kj::inf(), -kj::inf(), kj::nan()}); builder.setFloat64List({7777.75, kj::inf(), -kj::inf(), kj::nan()}); builder.setTextList({"plugh", "xyzzy", "thud"}); builder.setDataList({data("oops"), data("exhausted"), data("rfc3092")}); { auto listBuilder = builder.initStructList(3); listBuilder[0].setTextField("structlist 1"); listBuilder[1].setTextField("structlist 2"); listBuilder[2].setTextField("structlist 3"); } builder.setEnumList({TestEnum::FOO, TestEnum::GARPLY}); } #if !CAPNP_LITE void dynamicInitTestMessage(DynamicStruct::Builder builder) { builder.set("voidField", VOID); builder.set("boolField", true); builder.set("int8Field", -123); builder.set("int16Field", -12345); builder.set("int32Field", -12345678); builder.set("int64Field", -123456789012345ll); builder.set("uInt8Field", 234u); builder.set("uInt16Field", 45678u); builder.set("uInt32Field", 3456789012u); builder.set("uInt64Field", 12345678901234567890ull); builder.set("float32Field", 1234.5); builder.set("float64Field", -123e45); builder.set("textField", "foo"); builder.set("dataField", data("bar")); { auto subBuilder = builder.init("structField").as(); subBuilder.set("voidField", VOID); subBuilder.set("boolField", true); subBuilder.set("int8Field", -12); subBuilder.set("int16Field", 3456); subBuilder.set("int32Field", -78901234); subBuilder.set("int64Field", 56789012345678ll); subBuilder.set("uInt8Field", 90u); subBuilder.set("uInt16Field", 1234u); subBuilder.set("uInt32Field", 56789012u); subBuilder.set("uInt64Field", 345678901234567890ull); subBuilder.set("float32Field", -1.25e-10); subBuilder.set("float64Field", 345); subBuilder.set("textField", "baz"); subBuilder.set("dataField", data("qux")); { auto subSubBuilder = subBuilder.init("structField").as(); subSubBuilder.set("textField", "nested"); subSubBuilder.init("structField").as().set("textField", "really nested"); } subBuilder.set("enumField", "baz"); subBuilder.set("voidList", {VOID, VOID, VOID}); subBuilder.set("boolList", {false, true, false, true, true}); subBuilder.set("int8List", {12, -34, -0x80, 0x7f}); subBuilder.set("int16List", {1234, -5678, -0x8000, 0x7fff}); // gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1. subBuilder.set("int32List", {12345678, -90123456, -0x7fffffff - 1, 0x7fffffff}); subBuilder.set("int64List", {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll}); subBuilder.set("uInt8List", {12u, 34u, 0u, 0xffu}); subBuilder.set("uInt16List", {1234u, 5678u, 0u, 0xffffu}); subBuilder.set("uInt32List", {12345678u, 90123456u, 0u, 0xffffffffu}); subBuilder.set("uInt64List", {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull}); subBuilder.set("float32List", {0, 1234567, 1e37, -1e37, 1e-37, -1e-37}); subBuilder.set("float64List", {0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306}); subBuilder.set("textList", {"quux", "corge", "grault"}); subBuilder.set("dataList", {data("garply"), data("waldo"), data("fred")}); { auto listBuilder = subBuilder.init("structList", 3).as(); listBuilder[0].as().set("textField", "x structlist 1"); listBuilder[1].as().set("textField", "x structlist 2"); listBuilder[2].as().set("textField", "x structlist 3"); } subBuilder.set("enumList", {"qux", "bar", "grault"}); } builder.set("enumField", "corge"); builder.init("voidList", 6); builder.set("boolList", {true, false, false, true}); builder.set("int8List", {111, -111}); builder.set("int16List", {11111, -11111}); builder.set("int32List", {111111111, -111111111}); builder.set("int64List", {1111111111111111111ll, -1111111111111111111ll}); builder.set("uInt8List", {111u, 222u}); builder.set("uInt16List", {33333u, 44444u}); builder.set("uInt32List", {3333333333u}); builder.set("uInt64List", {11111111111111111111ull}); builder.set("float32List", {5555.5, kj::inf(), -kj::inf(), kj::nan()}); builder.set("float64List", {7777.75, kj::inf(), -kj::inf(), kj::nan()}); builder.set("textList", {"plugh", "xyzzy", "thud"}); builder.set("dataList", {data("oops"), data("exhausted"), data("rfc3092")}); { auto listBuilder = builder.init("structList", 3).as(); listBuilder[0].as().set("textField", "structlist 1"); listBuilder[1].as().set("textField", "structlist 2"); listBuilder[2].as().set("textField", "structlist 3"); } builder.set("enumList", {"foo", "garply"}); } #endif // !CAPNP_LITE inline bool isNaN(float f) { return f != f; } inline bool isNaN(double f) { return f != f; } template void genericCheckTestMessage(Reader reader) { EXPECT_EQ(VOID, reader.getVoidField()); EXPECT_EQ(true, reader.getBoolField()); EXPECT_EQ(-123, reader.getInt8Field()); EXPECT_EQ(-12345, reader.getInt16Field()); EXPECT_EQ(-12345678, reader.getInt32Field()); EXPECT_EQ(-123456789012345ll, reader.getInt64Field()); EXPECT_EQ(234u, reader.getUInt8Field()); EXPECT_EQ(45678u, reader.getUInt16Field()); EXPECT_EQ(3456789012u, reader.getUInt32Field()); EXPECT_EQ(12345678901234567890ull, reader.getUInt64Field()); EXPECT_FLOAT_EQ(1234.5f, reader.getFloat32Field()); EXPECT_DOUBLE_EQ(-123e45, reader.getFloat64Field()); EXPECT_EQ("foo", reader.getTextField()); EXPECT_EQ(data("bar"), reader.getDataField()); { auto subReader = reader.getStructField(); EXPECT_EQ(VOID, subReader.getVoidField()); EXPECT_EQ(true, subReader.getBoolField()); EXPECT_EQ(-12, subReader.getInt8Field()); EXPECT_EQ(3456, subReader.getInt16Field()); EXPECT_EQ(-78901234, subReader.getInt32Field()); EXPECT_EQ(56789012345678ll, subReader.getInt64Field()); EXPECT_EQ(90u, subReader.getUInt8Field()); EXPECT_EQ(1234u, subReader.getUInt16Field()); EXPECT_EQ(56789012u, subReader.getUInt32Field()); EXPECT_EQ(345678901234567890ull, subReader.getUInt64Field()); EXPECT_FLOAT_EQ(-1.25e-10f, subReader.getFloat32Field()); EXPECT_DOUBLE_EQ(345, subReader.getFloat64Field()); EXPECT_EQ("baz", subReader.getTextField()); EXPECT_EQ(data("qux"), subReader.getDataField()); { auto subSubReader = subReader.getStructField(); EXPECT_EQ("nested", subSubReader.getTextField()); EXPECT_EQ("really nested", subSubReader.getStructField().getTextField()); } EXPECT_EQ(TestEnum::BAZ, subReader.getEnumField()); checkList(subReader.getVoidList(), {VOID, VOID, VOID}); checkList(subReader.getBoolList(), {false, true, false, true, true}); checkList(subReader.getInt8List(), {12, -34, -0x80, 0x7f}); checkList(subReader.getInt16List(), {1234, -5678, -0x8000, 0x7fff}); // gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1. checkList(subReader.getInt32List(), {12345678, -90123456, -0x7fffffff - 1, 0x7fffffff}); checkList(subReader.getInt64List(), {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll}); checkList(subReader.getUInt8List(), {12u, 34u, 0u, 0xffu}); checkList(subReader.getUInt16List(), {1234u, 5678u, 0u, 0xffffu}); checkList(subReader.getUInt32List(), {12345678u, 90123456u, 0u, 0xffffffffu}); checkList(subReader.getUInt64List(), {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull}); checkList(subReader.getFloat32List(), {0.0f, 1234567.0f, 1e37f, -1e37f, 1e-37f, -1e-37f}); checkList(subReader.getFloat64List(), {0.0, 123456789012345.0, 1e306, -1e306, 1e-306, -1e-306}); checkList(subReader.getTextList(), {"quux", "corge", "grault"}); checkList(subReader.getDataList(), {data("garply"), data("waldo"), data("fred")}); { auto listReader = subReader.getStructList(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("x structlist 1", listReader[0].getTextField()); EXPECT_EQ("x structlist 2", listReader[1].getTextField()); EXPECT_EQ("x structlist 3", listReader[2].getTextField()); } checkList(subReader.getEnumList(), {TestEnum::QUX, TestEnum::BAR, TestEnum::GRAULT}); } EXPECT_EQ(TestEnum::CORGE, reader.getEnumField()); EXPECT_EQ(6u, reader.getVoidList().size()); checkList(reader.getBoolList(), {true, false, false, true}); checkList(reader.getInt8List(), {111, -111}); checkList(reader.getInt16List(), {11111, -11111}); checkList(reader.getInt32List(), {111111111, -111111111}); checkList(reader.getInt64List(), {1111111111111111111ll, -1111111111111111111ll}); checkList(reader.getUInt8List(), {111u, 222u}); checkList(reader.getUInt16List(), {33333u, 44444u}); checkList(reader.getUInt32List(), {3333333333u}); checkList(reader.getUInt64List(), {11111111111111111111ull}); { auto listReader = reader.getFloat32List(); ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(5555.5f, listReader[0]); EXPECT_EQ(kj::inf(), listReader[1]); EXPECT_EQ(-kj::inf(), listReader[2]); EXPECT_TRUE(isNaN(listReader[3])); } { auto listReader = reader.getFloat64List(); ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(7777.75, listReader[0]); EXPECT_EQ(kj::inf(), listReader[1]); EXPECT_EQ(-kj::inf(), listReader[2]); EXPECT_TRUE(isNaN(listReader[3])); } checkList(reader.getTextList(), {"plugh", "xyzzy", "thud"}); checkList(reader.getDataList(), {data("oops"), data("exhausted"), data("rfc3092")}); { auto listReader = reader.getStructList(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("structlist 1", listReader[0].getTextField()); EXPECT_EQ("structlist 2", listReader[1].getTextField()); EXPECT_EQ("structlist 3", listReader[2].getTextField()); } checkList(reader.getEnumList(), {TestEnum::FOO, TestEnum::GARPLY}); } #if !CAPNP_LITE // Hack because as<>() is a template-parameter-dependent lookup everywhere below... #define as template as Text::Reader name(DynamicEnum e) { KJ_IF_MAYBE(schema, e.getEnumerant()) { return schema->getProto().getName(); } else { return "(unknown enumerant)"; } } template void checkEnumList(T reader, std::initializer_list expected) { auto list = reader.as(); ASSERT_EQ(expected.size(), list.size()); for (uint i = 0; i < expected.size(); i++) { EXPECT_EQ(expected.begin()[i], name(list[i].as())); } } template void dynamicCheckTestMessage(Reader reader) { EXPECT_EQ(VOID, reader.get("voidField").as()); EXPECT_EQ(true, reader.get("boolField").as()); EXPECT_EQ(-123, reader.get("int8Field").as()); EXPECT_EQ(-12345, reader.get("int16Field").as()); EXPECT_EQ(-12345678, reader.get("int32Field").as()); EXPECT_EQ(-123456789012345ll, reader.get("int64Field").as()); EXPECT_EQ(234u, reader.get("uInt8Field").as()); EXPECT_EQ(45678u, reader.get("uInt16Field").as()); EXPECT_EQ(3456789012u, reader.get("uInt32Field").as()); EXPECT_EQ(12345678901234567890ull, reader.get("uInt64Field").as()); EXPECT_FLOAT_EQ(1234.5f, reader.get("float32Field").as()); EXPECT_DOUBLE_EQ(-123e45, reader.get("float64Field").as()); EXPECT_EQ("foo", reader.get("textField").as()); EXPECT_EQ(data("bar"), reader.get("dataField").as()); { auto subReader = reader.get("structField").as(); EXPECT_EQ(VOID, subReader.get("voidField").as()); EXPECT_EQ(true, subReader.get("boolField").as()); EXPECT_EQ(-12, subReader.get("int8Field").as()); EXPECT_EQ(3456, subReader.get("int16Field").as()); EXPECT_EQ(-78901234, subReader.get("int32Field").as()); EXPECT_EQ(56789012345678ll, subReader.get("int64Field").as()); EXPECT_EQ(90u, subReader.get("uInt8Field").as()); EXPECT_EQ(1234u, subReader.get("uInt16Field").as()); EXPECT_EQ(56789012u, subReader.get("uInt32Field").as()); EXPECT_EQ(345678901234567890ull, subReader.get("uInt64Field").as()); EXPECT_FLOAT_EQ(-1.25e-10f, subReader.get("float32Field").as()); EXPECT_DOUBLE_EQ(345, subReader.get("float64Field").as()); EXPECT_EQ("baz", subReader.get("textField").as()); EXPECT_EQ(data("qux"), subReader.get("dataField").as()); { auto subSubReader = subReader.get("structField").as(); EXPECT_EQ("nested", subSubReader.get("textField").as()); EXPECT_EQ("really nested", subSubReader.get("structField").as() .get("textField").as()); } EXPECT_EQ("baz", name(subReader.get("enumField").as())); checkList(subReader.get("voidList"), {VOID, VOID, VOID}); checkList(subReader.get("boolList"), {false, true, false, true, true}); checkList(subReader.get("int8List"), {12, -34, -0x80, 0x7f}); checkList(subReader.get("int16List"), {1234, -5678, -0x8000, 0x7fff}); // gcc warns on -0x800... and the only work-around I could find was to do -0x7ff...-1. checkList(subReader.get("int32List"), {12345678, -90123456, -0x7fffffff-1, 0x7fffffff}); checkList(subReader.get("int64List"), {123456789012345ll, -678901234567890ll, -0x7fffffffffffffffll-1, 0x7fffffffffffffffll}); checkList(subReader.get("uInt8List"), {12u, 34u, 0u, 0xffu}); checkList(subReader.get("uInt16List"), {1234u, 5678u, 0u, 0xffffu}); checkList(subReader.get("uInt32List"), {12345678u, 90123456u, 0u, 0xffffffffu}); checkList(subReader.get("uInt64List"), {123456789012345ull, 678901234567890ull, 0ull, 0xffffffffffffffffull}); checkList(subReader.get("float32List"), {0.0f, 1234567.0f, 1e37f, -1e37f, 1e-37f, -1e-37f}); checkList(subReader.get("float64List"), {0.0, 123456789012345.0, 1e306, -1e306, 1e-306, -1e-306}); checkList(subReader.get("textList"), {"quux", "corge", "grault"}); checkList(subReader.get("dataList"), {data("garply"), data("waldo"), data("fred")}); { auto listReader = subReader.get("structList").as(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("x structlist 1", listReader[0].as().get("textField").as()); EXPECT_EQ("x structlist 2", listReader[1].as().get("textField").as()); EXPECT_EQ("x structlist 3", listReader[2].as().get("textField").as()); } checkEnumList(subReader.get("enumList"), {"qux", "bar", "grault"}); } EXPECT_EQ("corge", name(reader.get("enumField").as())); EXPECT_EQ(6u, reader.get("voidList").as().size()); checkList(reader.get("boolList"), {true, false, false, true}); checkList(reader.get("int8List"), {111, -111}); checkList(reader.get("int16List"), {11111, -11111}); checkList(reader.get("int32List"), {111111111, -111111111}); checkList(reader.get("int64List"), {1111111111111111111ll, -1111111111111111111ll}); checkList(reader.get("uInt8List"), {111u, 222u}); checkList(reader.get("uInt16List"), {33333u, 44444u}); checkList(reader.get("uInt32List"), {3333333333u}); checkList(reader.get("uInt64List"), {11111111111111111111ull}); { auto listReader = reader.get("float32List").as(); ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(5555.5f, listReader[0].as()); EXPECT_EQ(kj::inf(), listReader[1].as()); EXPECT_EQ(-kj::inf(), listReader[2].as()); EXPECT_TRUE(isNaN(listReader[3].as())); } { auto listReader = reader.get("float64List").as(); ASSERT_EQ(4u, listReader.size()); EXPECT_EQ(7777.75, listReader[0].as()); EXPECT_EQ(kj::inf(), listReader[1].as()); EXPECT_EQ(-kj::inf(), listReader[2].as()); EXPECT_TRUE(isNaN(listReader[3].as())); } checkList(reader.get("textList"), {"plugh", "xyzzy", "thud"}); checkList(reader.get("dataList"), {data("oops"), data("exhausted"), data("rfc3092")}); { auto listReader = reader.get("structList").as(); ASSERT_EQ(3u, listReader.size()); EXPECT_EQ("structlist 1", listReader[0].as().get("textField").as()); EXPECT_EQ("structlist 2", listReader[1].as().get("textField").as()); EXPECT_EQ("structlist 3", listReader[2].as().get("textField").as()); } checkEnumList(reader.get("enumList"), {"foo", "garply"}); } #undef as #endif // !CAPNP_LITE template void genericCheckTestMessageAllZero(Reader reader) { EXPECT_EQ(VOID, reader.getVoidField()); EXPECT_EQ(false, reader.getBoolField()); EXPECT_EQ(0, reader.getInt8Field()); EXPECT_EQ(0, reader.getInt16Field()); EXPECT_EQ(0, reader.getInt32Field()); EXPECT_EQ(0, reader.getInt64Field()); EXPECT_EQ(0u, reader.getUInt8Field()); EXPECT_EQ(0u, reader.getUInt16Field()); EXPECT_EQ(0u, reader.getUInt32Field()); EXPECT_EQ(0u, reader.getUInt64Field()); EXPECT_FLOAT_EQ(0, reader.getFloat32Field()); EXPECT_DOUBLE_EQ(0, reader.getFloat64Field()); EXPECT_EQ("", reader.getTextField()); EXPECT_EQ(data(""), reader.getDataField()); { auto subReader = reader.getStructField(); EXPECT_EQ(VOID, subReader.getVoidField()); EXPECT_EQ(false, subReader.getBoolField()); EXPECT_EQ(0, subReader.getInt8Field()); EXPECT_EQ(0, subReader.getInt16Field()); EXPECT_EQ(0, subReader.getInt32Field()); EXPECT_EQ(0, subReader.getInt64Field()); EXPECT_EQ(0u, subReader.getUInt8Field()); EXPECT_EQ(0u, subReader.getUInt16Field()); EXPECT_EQ(0u, subReader.getUInt32Field()); EXPECT_EQ(0u, subReader.getUInt64Field()); EXPECT_FLOAT_EQ(0, subReader.getFloat32Field()); EXPECT_DOUBLE_EQ(0, subReader.getFloat64Field()); EXPECT_EQ("", subReader.getTextField()); EXPECT_EQ(data(""), subReader.getDataField()); { auto subSubReader = subReader.getStructField(); EXPECT_EQ("", subSubReader.getTextField()); EXPECT_EQ("", subSubReader.getStructField().getTextField()); } EXPECT_EQ(0u, subReader.getVoidList().size()); EXPECT_EQ(0u, subReader.getBoolList().size()); EXPECT_EQ(0u, subReader.getInt8List().size()); EXPECT_EQ(0u, subReader.getInt16List().size()); EXPECT_EQ(0u, subReader.getInt32List().size()); EXPECT_EQ(0u, subReader.getInt64List().size()); EXPECT_EQ(0u, subReader.getUInt8List().size()); EXPECT_EQ(0u, subReader.getUInt16List().size()); EXPECT_EQ(0u, subReader.getUInt32List().size()); EXPECT_EQ(0u, subReader.getUInt64List().size()); EXPECT_EQ(0u, subReader.getFloat32List().size()); EXPECT_EQ(0u, subReader.getFloat64List().size()); EXPECT_EQ(0u, subReader.getTextList().size()); EXPECT_EQ(0u, subReader.getDataList().size()); EXPECT_EQ(0u, subReader.getStructList().size()); } EXPECT_EQ(0u, reader.getVoidList().size()); EXPECT_EQ(0u, reader.getBoolList().size()); EXPECT_EQ(0u, reader.getInt8List().size()); EXPECT_EQ(0u, reader.getInt16List().size()); EXPECT_EQ(0u, reader.getInt32List().size()); EXPECT_EQ(0u, reader.getInt64List().size()); EXPECT_EQ(0u, reader.getUInt8List().size()); EXPECT_EQ(0u, reader.getUInt16List().size()); EXPECT_EQ(0u, reader.getUInt32List().size()); EXPECT_EQ(0u, reader.getUInt64List().size()); EXPECT_EQ(0u, reader.getFloat32List().size()); EXPECT_EQ(0u, reader.getFloat64List().size()); EXPECT_EQ(0u, reader.getTextList().size()); EXPECT_EQ(0u, reader.getDataList().size()); EXPECT_EQ(0u, reader.getStructList().size()); } #if !CAPNP_LITE // Hack because as<>() is a template-parameter-dependent lookup everywhere below... #define as template as template void dynamicCheckTestMessageAllZero(Reader reader) { EXPECT_EQ(VOID, reader.get("voidField").as()); EXPECT_EQ(false, reader.get("boolField").as()); EXPECT_EQ(0, reader.get("int8Field").as()); EXPECT_EQ(0, reader.get("int16Field").as()); EXPECT_EQ(0, reader.get("int32Field").as()); EXPECT_EQ(0, reader.get("int64Field").as()); EXPECT_EQ(0u, reader.get("uInt8Field").as()); EXPECT_EQ(0u, reader.get("uInt16Field").as()); EXPECT_EQ(0u, reader.get("uInt32Field").as()); EXPECT_EQ(0u, reader.get("uInt64Field").as()); EXPECT_FLOAT_EQ(0, reader.get("float32Field").as()); EXPECT_DOUBLE_EQ(0, reader.get("float64Field").as()); EXPECT_EQ("", reader.get("textField").as()); EXPECT_EQ(data(""), reader.get("dataField").as()); { auto subReader = reader.get("structField").as(); EXPECT_EQ(VOID, subReader.get("voidField").as()); EXPECT_EQ(false, subReader.get("boolField").as()); EXPECT_EQ(0, subReader.get("int8Field").as()); EXPECT_EQ(0, subReader.get("int16Field").as()); EXPECT_EQ(0, subReader.get("int32Field").as()); EXPECT_EQ(0, subReader.get("int64Field").as()); EXPECT_EQ(0u, subReader.get("uInt8Field").as()); EXPECT_EQ(0u, subReader.get("uInt16Field").as()); EXPECT_EQ(0u, subReader.get("uInt32Field").as()); EXPECT_EQ(0u, subReader.get("uInt64Field").as()); EXPECT_FLOAT_EQ(0, subReader.get("float32Field").as()); EXPECT_DOUBLE_EQ(0, subReader.get("float64Field").as()); EXPECT_EQ("", subReader.get("textField").as()); EXPECT_EQ(data(""), subReader.get("dataField").as()); { auto subSubReader = subReader.get("structField").as(); EXPECT_EQ("", subSubReader.get("textField").as()); EXPECT_EQ("", subSubReader.get("structField").as() .get("textField").as()); } EXPECT_EQ(0u, subReader.get("voidList").as().size()); EXPECT_EQ(0u, subReader.get("boolList").as().size()); EXPECT_EQ(0u, subReader.get("int8List").as().size()); EXPECT_EQ(0u, subReader.get("int16List").as().size()); EXPECT_EQ(0u, subReader.get("int32List").as().size()); EXPECT_EQ(0u, subReader.get("int64List").as().size()); EXPECT_EQ(0u, subReader.get("uInt8List").as().size()); EXPECT_EQ(0u, subReader.get("uInt16List").as().size()); EXPECT_EQ(0u, subReader.get("uInt32List").as().size()); EXPECT_EQ(0u, subReader.get("uInt64List").as().size()); EXPECT_EQ(0u, subReader.get("float32List").as().size()); EXPECT_EQ(0u, subReader.get("float64List").as().size()); EXPECT_EQ(0u, subReader.get("textList").as().size()); EXPECT_EQ(0u, subReader.get("dataList").as().size()); EXPECT_EQ(0u, subReader.get("structList").as().size()); } EXPECT_EQ(0u, reader.get("voidList").as().size()); EXPECT_EQ(0u, reader.get("boolList").as().size()); EXPECT_EQ(0u, reader.get("int8List").as().size()); EXPECT_EQ(0u, reader.get("int16List").as().size()); EXPECT_EQ(0u, reader.get("int32List").as().size()); EXPECT_EQ(0u, reader.get("int64List").as().size()); EXPECT_EQ(0u, reader.get("uInt8List").as().size()); EXPECT_EQ(0u, reader.get("uInt16List").as().size()); EXPECT_EQ(0u, reader.get("uInt32List").as().size()); EXPECT_EQ(0u, reader.get("uInt64List").as().size()); EXPECT_EQ(0u, reader.get("float32List").as().size()); EXPECT_EQ(0u, reader.get("float64List").as().size()); EXPECT_EQ(0u, reader.get("textList").as().size()); EXPECT_EQ(0u, reader.get("dataList").as().size()); EXPECT_EQ(0u, reader.get("structList").as().size()); } #undef as #endif // !CAPNP_LITE template void genericInitListDefaults(Builder builder) { auto lists = builder.initLists(); lists.initList0(2); lists.initList1(4); lists.initList8(2); lists.initList16(2); lists.initList32(2); lists.initList64(2); lists.initListP(2); lists.getList0()[0].setF(VOID); lists.getList0()[1].setF(VOID); lists.getList1()[0].setF(true); lists.getList1()[1].setF(false); lists.getList1()[2].setF(true); lists.getList1()[3].setF(true); lists.getList8()[0].setF(123u); lists.getList8()[1].setF(45u); lists.getList16()[0].setF(12345u); lists.getList16()[1].setF(6789u); lists.getList32()[0].setF(123456789u); lists.getList32()[1].setF(234567890u); lists.getList64()[0].setF(1234567890123456u); lists.getList64()[1].setF(2345678901234567u); lists.getListP()[0].setF("foo"); lists.getListP()[1].setF("bar"); { auto l = lists.initInt32ListList(3); l.set(0, {1, 2, 3}); l.set(1, {4, 5}); l.set(2, {12341234}); } { auto l = lists.initTextListList(3); l.set(0, {"foo", "bar"}); l.set(1, {"baz"}); l.set(2, {"qux", "corge"}); } { auto l = lists.initStructListList(2); auto e = l.init(0, 2); e[0].setInt32Field(123); e[1].setInt32Field(456); e = l.init(1, 1); e[0].setInt32Field(789); } } #if !CAPNP_LITE void dynamicInitListDefaults(DynamicStruct::Builder builder) { auto lists = builder.init("lists").as(); lists.init("list0", 2); lists.init("list1", 4); lists.init("list8", 2); lists.init("list16", 2); lists.init("list32", 2); lists.init("list64", 2); lists.init("listP", 2); lists.get("list0").as()[0].as().set("f", VOID); lists.get("list0").as()[1].as().set("f", VOID); lists.get("list1").as()[0].as().set("f", true); lists.get("list1").as()[1].as().set("f", false); lists.get("list1").as()[2].as().set("f", true); lists.get("list1").as()[3].as().set("f", true); lists.get("list8").as()[0].as().set("f", 123u); lists.get("list8").as()[1].as().set("f", 45u); lists.get("list16").as()[0].as().set("f", 12345u); lists.get("list16").as()[1].as().set("f", 6789u); lists.get("list32").as()[0].as().set("f", 123456789u); lists.get("list32").as()[1].as().set("f", 234567890u); lists.get("list64").as()[0].as().set("f", 1234567890123456u); lists.get("list64").as()[1].as().set("f", 2345678901234567u); lists.get("listP").as()[0].as().set("f", "foo"); lists.get("listP").as()[1].as().set("f", "bar"); { auto l = lists.init("int32ListList", 3).as(); l.init(0, 3).as().copyFrom({1, 2, 3}); l.init(1, 2).as().copyFrom({4, 5}); l.init(2, 1).as().copyFrom({12341234}); } { auto l = lists.init("textListList", 3).as(); l.init(0, 2).as().copyFrom({"foo", "bar"}); l.init(1, 1).as().copyFrom({"baz"}); l.init(2, 2).as().copyFrom({"qux", "corge"}); } { auto l = lists.init("structListList", 2).as(); auto e = l.init(0, 2).as(); e[0].as().setInt32Field(123); e[1].as().setInt32Field(456); e = l.init(1, 1).as(); e[0].as().setInt32Field(789); } } #endif // !CAPNP_LITE template void genericCheckListDefaults(Reader reader) { auto lists = reader.getLists(); ASSERT_EQ(2u, lists.getList0().size()); ASSERT_EQ(4u, lists.getList1().size()); ASSERT_EQ(2u, lists.getList8().size()); ASSERT_EQ(2u, lists.getList16().size()); ASSERT_EQ(2u, lists.getList32().size()); ASSERT_EQ(2u, lists.getList64().size()); ASSERT_EQ(2u, lists.getListP().size()); EXPECT_EQ(VOID, lists.getList0()[0].getF()); EXPECT_EQ(VOID, lists.getList0()[1].getF()); EXPECT_TRUE(lists.getList1()[0].getF()); EXPECT_FALSE(lists.getList1()[1].getF()); EXPECT_TRUE(lists.getList1()[2].getF()); EXPECT_TRUE(lists.getList1()[3].getF()); EXPECT_EQ(123u, lists.getList8()[0].getF()); EXPECT_EQ(45u, lists.getList8()[1].getF()); EXPECT_EQ(12345u, lists.getList16()[0].getF()); EXPECT_EQ(6789u, lists.getList16()[1].getF()); EXPECT_EQ(123456789u, lists.getList32()[0].getF()); EXPECT_EQ(234567890u, lists.getList32()[1].getF()); EXPECT_EQ(1234567890123456u, lists.getList64()[0].getF()); EXPECT_EQ(2345678901234567u, lists.getList64()[1].getF()); EXPECT_EQ("foo", lists.getListP()[0].getF()); EXPECT_EQ("bar", lists.getListP()[1].getF()); { auto l = lists.getInt32ListList(); ASSERT_EQ(3u, l.size()); checkList(l[0], {1, 2, 3}); checkList(l[1], {4, 5}); checkList(l[2], {12341234}); } { auto l = lists.getTextListList(); ASSERT_EQ(3u, l.size()); checkList(l[0], {"foo", "bar"}); checkList(l[1], {"baz"}); checkList(l[2], {"qux", "corge"}); } { auto l = lists.getStructListList(); ASSERT_EQ(2u, l.size()); auto e = l[0]; ASSERT_EQ(2u, e.size()); EXPECT_EQ(123, e[0].getInt32Field()); EXPECT_EQ(456, e[1].getInt32Field()); e = l[1]; ASSERT_EQ(1u, e.size()); EXPECT_EQ(789, e[0].getInt32Field()); } } #if !CAPNP_LITE // Hack because as<>() is a template-parameter-dependent lookup everywhere below... #define as template as template void dynamicCheckListDefaults(Reader reader) { auto lists = reader.get("lists").as(); ASSERT_EQ(2u, lists.get("list0").as().size()); ASSERT_EQ(4u, lists.get("list1").as().size()); ASSERT_EQ(2u, lists.get("list8").as().size()); ASSERT_EQ(2u, lists.get("list16").as().size()); ASSERT_EQ(2u, lists.get("list32").as().size()); ASSERT_EQ(2u, lists.get("list64").as().size()); ASSERT_EQ(2u, lists.get("listP").as().size()); EXPECT_EQ(VOID, lists.get("list0").as()[0].as().get("f").as()); EXPECT_EQ(VOID, lists.get("list0").as()[1].as().get("f").as()); EXPECT_TRUE(lists.get("list1").as()[0].as().get("f").as()); EXPECT_FALSE(lists.get("list1").as()[1].as().get("f").as()); EXPECT_TRUE(lists.get("list1").as()[2].as().get("f").as()); EXPECT_TRUE(lists.get("list1").as()[3].as().get("f").as()); EXPECT_EQ(123u, lists.get("list8").as()[0].as().get("f").as()); EXPECT_EQ(45u, lists.get("list8").as()[1].as().get("f").as()); EXPECT_EQ(12345u, lists.get("list16").as()[0].as().get("f").as()); EXPECT_EQ(6789u, lists.get("list16").as()[1].as().get("f").as()); EXPECT_EQ(123456789u, lists.get("list32").as()[0].as().get("f").as()); EXPECT_EQ(234567890u, lists.get("list32").as()[1].as().get("f").as()); EXPECT_EQ(1234567890123456u, lists.get("list64").as()[0].as().get("f").as()); EXPECT_EQ(2345678901234567u, lists.get("list64").as()[1].as().get("f").as()); EXPECT_EQ("foo", lists.get("listP").as()[0].as().get("f").as()); EXPECT_EQ("bar", lists.get("listP").as()[1].as().get("f").as()); { auto l = lists.get("int32ListList").as(); ASSERT_EQ(3u, l.size()); checkList(l[0], {1, 2, 3}); checkList(l[1], {4, 5}); checkList(l[2], {12341234}); } { auto l = lists.get("textListList").as(); ASSERT_EQ(3u, l.size()); checkList(l[0], {"foo", "bar"}); checkList(l[1], {"baz"}); checkList(l[2], {"qux", "corge"}); } { auto l = lists.get("structListList").as(); ASSERT_EQ(2u, l.size()); auto e = l[0].as(); ASSERT_EQ(2u, e.size()); EXPECT_EQ(123, e[0].as().getInt32Field()); EXPECT_EQ(456, e[1].as().getInt32Field()); e = l[1].as(); ASSERT_EQ(1u, e.size()); EXPECT_EQ(789, e[0].as().getInt32Field()); } } #undef as #endif // !CAPNP_LITE } // namespace void initTestMessage(TestAllTypes::Builder builder) { genericInitTestMessage(builder); } void initTestMessage(TestDefaults::Builder builder) { genericInitTestMessage(builder); } void initTestMessage(TestListDefaults::Builder builder) { genericInitListDefaults(builder); } void checkTestMessage(TestAllTypes::Builder builder) { genericCheckTestMessage(builder); } void checkTestMessage(TestDefaults::Builder builder) { genericCheckTestMessage(builder); } void checkTestMessage(TestListDefaults::Builder builder) { genericCheckListDefaults(builder); } void checkTestMessage(TestAllTypes::Reader reader) { genericCheckTestMessage(reader); } void checkTestMessage(TestDefaults::Reader reader) { genericCheckTestMessage(reader); } void checkTestMessage(TestListDefaults::Reader reader) { genericCheckListDefaults(reader); } void checkTestMessageAllZero(TestAllTypes::Builder builder) { genericCheckTestMessageAllZero(builder); } void checkTestMessageAllZero(TestAllTypes::Reader reader) { genericCheckTestMessageAllZero(reader); } #if !CAPNP_LITE void initDynamicTestMessage(DynamicStruct::Builder builder) { dynamicInitTestMessage(builder); } void initDynamicTestLists(DynamicStruct::Builder builder) { dynamicInitListDefaults(builder); } void checkDynamicTestMessage(DynamicStruct::Builder builder) { dynamicCheckTestMessage(builder); } void checkDynamicTestLists(DynamicStruct::Builder builder) { dynamicCheckListDefaults(builder); } void checkDynamicTestMessage(DynamicStruct::Reader reader) { dynamicCheckTestMessage(reader); } void checkDynamicTestLists(DynamicStruct::Reader reader) { dynamicCheckListDefaults(reader); } void checkDynamicTestMessageAllZero(DynamicStruct::Builder builder) { dynamicCheckTestMessageAllZero(builder); } void checkDynamicTestMessageAllZero(DynamicStruct::Reader reader) { dynamicCheckTestMessageAllZero(reader); } #endif // !CAPNP_LITE // ======================================================================================= // Interface implementations. #if !CAPNP_LITE TestInterfaceImpl::TestInterfaceImpl(int& callCount): callCount(callCount) {} kj::Promise TestInterfaceImpl::foo(FooContext context) { ++callCount; auto params = context.getParams(); auto result = context.getResults(); EXPECT_EQ(123, params.getI()); EXPECT_TRUE(params.getJ()); result.setX("foo"); return kj::READY_NOW; } kj::Promise TestInterfaceImpl::baz(BazContext context) { ++callCount; auto params = context.getParams(); checkTestMessage(params.getS()); context.releaseParams(); EXPECT_ANY_THROW(context.getParams()); return kj::READY_NOW; } TestExtendsImpl::TestExtendsImpl(int& callCount): callCount(callCount) {} kj::Promise TestExtendsImpl::foo(FooContext context) { ++callCount; auto params = context.getParams(); auto result = context.getResults(); EXPECT_EQ(321, params.getI()); EXPECT_FALSE(params.getJ()); result.setX("bar"); return kj::READY_NOW; } kj::Promise TestExtendsImpl::grault(GraultContext context) { ++callCount; context.releaseParams(); initTestMessage(context.getResults()); return kj::READY_NOW; } TestPipelineImpl::TestPipelineImpl(int& callCount): callCount(callCount) {} kj::Promise TestPipelineImpl::getCap(GetCapContext context) { ++callCount; auto params = context.getParams(); EXPECT_EQ(234, params.getN()); auto cap = params.getInCap(); context.releaseParams(); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [this,KJ_CPCAP(context)](Response&& response) mutable { EXPECT_EQ("foo", response.getX()); auto result = context.getResults(); result.setS("bar"); result.initOutBox().setCap(kj::heap(callCount)); }); } kj::Promise TestPipelineImpl::getAnyCap(GetAnyCapContext context) { ++callCount; auto params = context.getParams(); EXPECT_EQ(234, params.getN()); auto cap = params.getInCap(); context.releaseParams(); auto request = cap.castAs().fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [this,KJ_CPCAP(context)](Response&& response) mutable { EXPECT_EQ("foo", response.getX()); auto result = context.getResults(); result.setS("bar"); result.initOutBox().setCap(kj::heap(callCount)); }); } kj::Promise TestPipelineImpl::getCapPipelineOnly(GetCapPipelineOnlyContext context) { ++callCount; PipelineBuilder pb; pb.initOutBox().setCap(kj::heap(callCount)); context.setPipeline(pb.build()); return kj::NEVER_DONE; } kj::Promise TestCallOrderImpl::getCallSequence(GetCallSequenceContext context) { auto result = context.getResults(); result.setN(count++); return kj::READY_NOW; } TestTailCallerImpl::TestTailCallerImpl(int& callCount): callCount(callCount) {} kj::Promise TestTailCallerImpl::foo(FooContext context) { ++callCount; auto params = context.getParams(); auto tailRequest = params.getCallee().fooRequest(); tailRequest.setI(params.getI()); tailRequest.setT("from TestTailCaller"); return context.tailCall(kj::mv(tailRequest)); } TestTailCalleeImpl::TestTailCalleeImpl(int& callCount): callCount(callCount) {} kj::Promise TestTailCalleeImpl::foo(FooContext context) { ++callCount; auto params = context.getParams(); auto results = context.getResults(); results.setI(params.getI()); results.setT(params.getT()); results.setC(kj::heap()); return kj::READY_NOW; } TestMoreStuffImpl::TestMoreStuffImpl(int& callCount, int& handleCount) : callCount(callCount), handleCount(handleCount) {} kj::Promise TestMoreStuffImpl::getCallSequence(GetCallSequenceContext context) { auto result = context.getResults(); result.setN(callCount++); return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::callFoo(CallFooContext context) { ++callCount; auto params = context.getParams(); auto cap = params.getCap(); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [KJ_CPCAP(context)](Response&& response) mutable { EXPECT_EQ("foo", response.getX()); context.getResults().setS("bar"); }); } kj::Promise TestMoreStuffImpl::callFooWhenResolved(CallFooWhenResolvedContext context) { ++callCount; auto params = context.getParams(); auto cap = params.getCap(); return cap.whenResolved().then([KJ_CPCAP(cap),KJ_CPCAP(context)]() mutable { auto request = cap.fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [KJ_CPCAP(context)](Response&& response) mutable { EXPECT_EQ("foo", response.getX()); context.getResults().setS("bar"); }); }); } kj::Promise TestMoreStuffImpl::neverReturn(NeverReturnContext context) { ++callCount; // Attach `cap` to the promise to make sure it is released. auto promise = kj::Promise(kj::NEVER_DONE).attach(context.getParams().getCap()); // Also attach `cap` to the result struct to make sure that is released. context.getResults().setCapCopy(context.getParams().getCap()); return kj::mv(promise); } kj::Promise TestMoreStuffImpl::hold(HoldContext context) { ++callCount; auto params = context.getParams(); clientToHold = params.getCap(); return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::callHeld(CallHeldContext context) { ++callCount; auto request = clientToHold.fooRequest(); request.setI(123); request.setJ(true); return request.send().then( [KJ_CPCAP(context)](Response&& response) mutable { EXPECT_EQ("foo", response.getX()); context.getResults().setS("bar"); }); } kj::Promise TestMoreStuffImpl::getHeld(GetHeldContext context) { ++callCount; auto result = context.getResults(); result.setCap(clientToHold); return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::echo(EchoContext context) { ++callCount; auto params = context.getParams(); auto result = context.getResults(); result.setCap(params.getCap()); return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::expectCancel(ExpectCancelContext context) { auto cap = context.getParams().getCap(); return loop(0, cap, context); } kj::Promise TestMoreStuffImpl::loop(uint depth, test::TestInterface::Client cap, ExpectCancelContext context) { if (depth > 100) { ADD_FAILURE() << "Looped too long, giving up."; return kj::READY_NOW; } else { return kj::evalLast([this,depth,KJ_CPCAP(cap),KJ_CPCAP(context)]() mutable { return loop(depth + 1, cap, context); }); } } class HandleImpl final: public test::TestHandle::Server { public: HandleImpl(int& count): count(count) { ++count; } ~HandleImpl() { --count; } private: int& count; }; kj::Promise TestMoreStuffImpl::getHandle(GetHandleContext context) { context.getResults().setHandle(kj::heap(handleCount)); return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::getNull(GetNullContext context) { return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::getEnormousString(GetEnormousStringContext context) { context.getResults().initStr(100000000); // 100MB return kj::READY_NOW; } kj::Promise TestMoreStuffImpl::writeToFd(WriteToFdContext context) { auto params = context.getParams(); auto promises = kj::heapArrayBuilder>(2); promises.add(params.getFdCap1().getFd() .then([](kj::Maybe fd) { kj::FdOutputStream(KJ_ASSERT_NONNULL(fd)).write("foo", 3); })); promises.add(params.getFdCap2().getFd() .then([context](kj::Maybe fd) mutable { context.getResults().setSecondFdPresent(fd != nullptr); KJ_IF_MAYBE(f, fd) { kj::FdOutputStream(*f).write("bar", 3); } })); int pair[2]; KJ_SYSCALL(kj::miniposix::pipe(pair)); kj::AutoCloseFd in(pair[0]); kj::AutoCloseFd out(pair[1]); kj::FdOutputStream(kj::mv(out)).write("baz", 3); context.getResults().setFdCap3(kj::heap(kj::mv(in))); return kj::joinPromises(promises.finish()); } kj::Promise TestMoreStuffImpl::throwException(ThrowExceptionContext context) { return KJ_EXCEPTION(FAILED, "test exception"); } kj::Promise TestMoreStuffImpl::throwRemoteException(ThrowRemoteExceptionContext context) { return KJ_EXCEPTION(FAILED, "remote exception: test exception"); } #endif // !CAPNP_LITE } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize-packed.c++0000644000175000017500000003720514712011043022340 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "serialize-packed.h" #include #include "layout.h" #include namespace capnp { namespace _ { // private PackedInputStream::PackedInputStream(kj::BufferedInputStream& inner): inner(inner) {} PackedInputStream::~PackedInputStream() noexcept(false) {} size_t PackedInputStream::tryRead(void* dst, size_t minBytes, size_t maxBytes) { if (maxBytes == 0) { return 0; } KJ_DREQUIRE(minBytes % sizeof(word) == 0, "PackedInputStream reads must be word-aligned."); KJ_DREQUIRE(maxBytes % sizeof(word) == 0, "PackedInputStream reads must be word-aligned."); uint8_t* __restrict__ out = reinterpret_cast(dst); uint8_t* const outEnd = reinterpret_cast(dst) + maxBytes; uint8_t* const outMin = reinterpret_cast(dst) + minBytes; kj::ArrayPtr buffer = inner.tryGetReadBuffer(); if (buffer.size() == 0) { return 0; } const uint8_t* __restrict__ in = reinterpret_cast(buffer.begin()); #define REFRESH_BUFFER() \ inner.skip(buffer.size()); \ buffer = inner.getReadBuffer(); \ KJ_REQUIRE(buffer.size() > 0, "Premature end of packed input.") { \ return out - reinterpret_cast(dst); \ } \ in = reinterpret_cast(buffer.begin()) #define BUFFER_END (reinterpret_cast(buffer.end())) #define BUFFER_REMAINING ((size_t)(BUFFER_END - in)) for (;;) { uint8_t tag; KJ_DASSERT((out - reinterpret_cast(dst)) % sizeof(word) == 0, "Output pointer should always be aligned here."); if (BUFFER_REMAINING < 10) { if (out >= outMin) { // We read at least the minimum amount, so go ahead and return. inner.skip(in - reinterpret_cast(buffer.begin())); return out - reinterpret_cast(dst); } if (BUFFER_REMAINING == 0) { REFRESH_BUFFER(); continue; } // We have at least 1, but not 10, bytes available. We need to read slowly, doing a bounds // check on each byte. tag = *in++; for (uint i = 0; i < 8; i++) { if (tag & (1u << i)) { if (BUFFER_REMAINING == 0) { REFRESH_BUFFER(); } *out++ = *in++; } else { *out++ = 0; } } if (BUFFER_REMAINING == 0 && (tag == 0 || tag == 0xffu)) { REFRESH_BUFFER(); } } else { tag = *in++; #define HANDLE_BYTE(n) \ { \ bool isNonzero = (tag & (1u << n)) != 0; \ *out++ = *in & (-(int8_t)isNonzero); \ in += isNonzero; \ } HANDLE_BYTE(0); HANDLE_BYTE(1); HANDLE_BYTE(2); HANDLE_BYTE(3); HANDLE_BYTE(4); HANDLE_BYTE(5); HANDLE_BYTE(6); HANDLE_BYTE(7); #undef HANDLE_BYTE } if (tag == 0) { KJ_DASSERT(BUFFER_REMAINING > 0, "Should always have non-empty buffer here."); uint runLength = *in++ * sizeof(word); KJ_REQUIRE(runLength <= outEnd - out, "Packed input did not end cleanly on a segment boundary.") { return out - reinterpret_cast(dst); } memset(out, 0, runLength); out += runLength; } else if (tag == 0xffu) { KJ_DASSERT(BUFFER_REMAINING > 0, "Should always have non-empty buffer here."); uint runLength = *in++ * sizeof(word); KJ_REQUIRE(runLength <= outEnd - out, "Packed input did not end cleanly on a segment boundary.") { return out - reinterpret_cast(dst); } size_t inRemaining = BUFFER_REMAINING; if (inRemaining >= runLength) { // Fast path. memcpy(out, in, runLength); out += runLength; in += runLength; } else { // Copy over the first buffer, then do one big read for the rest. memcpy(out, in, inRemaining); out += inRemaining; runLength -= inRemaining; inner.skip(buffer.size()); inner.read(out, runLength); out += runLength; if (out == outEnd) { return maxBytes; } else { buffer = inner.getReadBuffer(); in = reinterpret_cast(buffer.begin()); // Skip the bounds check below since we just did the same check above. continue; } } } if (out == outEnd) { inner.skip(in - reinterpret_cast(buffer.begin())); return maxBytes; } } KJ_FAIL_ASSERT("Can't get here."); return 0; // GCC knows KJ_FAIL_ASSERT doesn't return, but Eclipse CDT still warns... #undef REFRESH_BUFFER } void PackedInputStream::skip(size_t bytes) { // We can't just read into buffers because buffers must end on block boundaries. if (bytes == 0) { return; } KJ_DREQUIRE(bytes % sizeof(word) == 0, "PackedInputStream reads must be word-aligned."); kj::ArrayPtr buffer = inner.getReadBuffer(); const uint8_t* __restrict__ in = reinterpret_cast(buffer.begin()); #define REFRESH_BUFFER() \ inner.skip(buffer.size()); \ buffer = inner.getReadBuffer(); \ KJ_REQUIRE(buffer.size() > 0, "Premature end of packed input.") { return; } \ in = reinterpret_cast(buffer.begin()) for (;;) { uint8_t tag; if (BUFFER_REMAINING < 10) { if (BUFFER_REMAINING == 0) { REFRESH_BUFFER(); continue; } // We have at least 1, but not 10, bytes available. We need to read slowly, doing a bounds // check on each byte. tag = *in++; for (uint i = 0; i < 8; i++) { if (tag & (1u << i)) { if (BUFFER_REMAINING == 0) { REFRESH_BUFFER(); } in++; } } bytes -= 8; if (BUFFER_REMAINING == 0 && (tag == 0 || tag == 0xffu)) { REFRESH_BUFFER(); } } else { tag = *in++; #define HANDLE_BYTE(n) \ in += (tag & (1u << n)) != 0 HANDLE_BYTE(0); HANDLE_BYTE(1); HANDLE_BYTE(2); HANDLE_BYTE(3); HANDLE_BYTE(4); HANDLE_BYTE(5); HANDLE_BYTE(6); HANDLE_BYTE(7); #undef HANDLE_BYTE bytes -= 8; } if (tag == 0) { KJ_DASSERT(BUFFER_REMAINING > 0, "Should always have non-empty buffer here."); uint runLength = *in++ * sizeof(word); KJ_REQUIRE(runLength <= bytes, "Packed input did not end cleanly on a segment boundary.") { return; } bytes -= runLength; } else if (tag == 0xffu) { KJ_DASSERT(BUFFER_REMAINING > 0, "Should always have non-empty buffer here."); uint runLength = *in++ * sizeof(word); KJ_REQUIRE(runLength <= bytes, "Packed input did not end cleanly on a segment boundary.") { return; } bytes -= runLength; size_t inRemaining = BUFFER_REMAINING; if (inRemaining > runLength) { // Fast path. in += runLength; } else { // Forward skip to the underlying stream. runLength -= inRemaining; inner.skip(buffer.size() + runLength); if (bytes == 0) { return; } else { buffer = inner.getReadBuffer(); in = reinterpret_cast(buffer.begin()); // Skip the bounds check below since we just did the same check above. continue; } } } if (bytes == 0) { inner.skip(in - reinterpret_cast(buffer.begin())); return; } } KJ_FAIL_ASSERT("Can't get here."); } // ------------------------------------------------------------------- PackedOutputStream::PackedOutputStream(kj::BufferedOutputStream& inner) : inner(inner) {} PackedOutputStream::~PackedOutputStream() noexcept(false) {} void PackedOutputStream::write(const void* src, size_t size) { kj::ArrayPtr buffer = inner.getWriteBuffer(); byte slowBuffer[20]; uint8_t* __restrict__ out = reinterpret_cast(buffer.begin()); const uint8_t* __restrict__ in = reinterpret_cast(src); const uint8_t* const inEnd = reinterpret_cast(src) + size; while (in < inEnd) { if (reinterpret_cast(buffer.end()) - out < 10) { // Oops, we're out of space. We need at least 10 bytes for the fast path, since we don't // bounds-check on every byte. // Write what we have so far. inner.write(buffer.begin(), out - reinterpret_cast(buffer.begin())); // Use a slow buffer into which we'll encode 10 to 20 bytes. This should get us past the // output stream's buffer boundary. buffer = kj::arrayPtr(slowBuffer, sizeof(slowBuffer)); out = reinterpret_cast(buffer.begin()); } uint8_t* tagPos = out++; #define HANDLE_BYTE(n) \ uint8_t bit##n = *in != 0; \ *out = *in; \ out += bit##n; /* out only advances if the byte was non-zero */ \ ++in HANDLE_BYTE(0); HANDLE_BYTE(1); HANDLE_BYTE(2); HANDLE_BYTE(3); HANDLE_BYTE(4); HANDLE_BYTE(5); HANDLE_BYTE(6); HANDLE_BYTE(7); #undef HANDLE_BYTE uint8_t tag = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3) | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7); *tagPos = tag; if (tag == 0) { // An all-zero word is followed by a count of consecutive zero words (not including the // first one). // We can check a whole word at a time. (Here is where we use the assumption that // `src` is word-aligned.) const uint64_t* inWord = reinterpret_cast(in); // The count must fit it 1 byte, so limit to 255 words. const uint64_t* limit = reinterpret_cast(inEnd); if (limit - inWord > 255) { limit = inWord + 255; } while (inWord < limit && *inWord == 0) { ++inWord; } // Write the count. *out++ = inWord - reinterpret_cast(in); // Advance input. in = reinterpret_cast(inWord); } else if (tag == 0xffu) { // An all-nonzero word is followed by a count of consecutive uncompressed words, followed // by the uncompressed words themselves. // Count the number of consecutive words in the input which have no more than a single // zero-byte. We look for at least two zeros because that's the point where our compression // scheme becomes a net win. // TODO(perf): Maybe look for three zeros? Compressing a two-zero word is a loss if the // following word has no zeros. const uint8_t* runStart = in; const uint8_t* limit = inEnd; if ((size_t)(limit - in) > 255 * sizeof(word)) { limit = in + 255 * sizeof(word); } while (in < limit) { // Check eight input bytes for zeros. uint c = *in++ == 0; c += *in++ == 0; c += *in++ == 0; c += *in++ == 0; c += *in++ == 0; c += *in++ == 0; c += *in++ == 0; c += *in++ == 0; if (c >= 2) { // Un-read the word with multiple zeros, since we'll want to compress that one. in -= 8; break; } } // Write the count. uint count = in - runStart; *out++ = count / sizeof(word); if (count <= reinterpret_cast(buffer.end()) - out) { // There's enough space to memcpy. memcpy(out, runStart, count); out += count; } else { // Input overruns the output buffer. We'll give it to the output stream in one chunk // and let it decide what to do. inner.write(buffer.begin(), reinterpret_cast(out) - buffer.begin()); inner.write(runStart, in - runStart); buffer = inner.getWriteBuffer(); out = reinterpret_cast(buffer.begin()); } } } // Write whatever is left. inner.write(buffer.begin(), reinterpret_cast(out) - buffer.begin()); } } // namespace _ (private) // ======================================================================================= PackedMessageReader::PackedMessageReader( kj::BufferedInputStream& inputStream, ReaderOptions options, kj::ArrayPtr scratchSpace) : PackedInputStream(inputStream), InputStreamMessageReader(static_cast(*this), options, scratchSpace) {} PackedMessageReader::~PackedMessageReader() noexcept(false) {} PackedFdMessageReader::PackedFdMessageReader( int fd, ReaderOptions options, kj::ArrayPtr scratchSpace) : FdInputStream(fd), BufferedInputStreamWrapper(static_cast(*this)), PackedMessageReader(static_cast(*this), options, scratchSpace) {} PackedFdMessageReader::PackedFdMessageReader( kj::AutoCloseFd fd, ReaderOptions options, kj::ArrayPtr scratchSpace) : FdInputStream(kj::mv(fd)), BufferedInputStreamWrapper(static_cast(*this)), PackedMessageReader(static_cast(*this), options, scratchSpace) {} PackedFdMessageReader::~PackedFdMessageReader() noexcept(false) {} void writePackedMessage(kj::BufferedOutputStream& output, kj::ArrayPtr> segments) { _::PackedOutputStream packedOutput(output); writeMessage(packedOutput, segments); } void writePackedMessage(kj::OutputStream& output, kj::ArrayPtr> segments) { KJ_IF_MAYBE(bufferedOutputPtr, kj::dynamicDowncastIfAvailable(output)) { writePackedMessage(*bufferedOutputPtr, segments); } else { byte buffer[8192]; kj::BufferedOutputStreamWrapper bufferedOutput(output, kj::arrayPtr(buffer, sizeof(buffer))); writePackedMessage(bufferedOutput, segments); } } void writePackedMessageToFd(int fd, kj::ArrayPtr> segments) { kj::FdOutputStream output(fd); writePackedMessage(output, segments); } size_t computeUnpackedSizeInWords(kj::ArrayPtr packedBytes) { const byte* ptr = packedBytes.begin(); const byte* end = packedBytes.end(); size_t total = 0; while (ptr < end) { uint tag = *ptr; size_t count = kj::popCount(tag); total += 1; KJ_REQUIRE(end - ptr >= count, "invalid packed data"); ptr += count + 1; if (tag == 0) { KJ_REQUIRE(ptr < end, "invalid packed data"); total += *ptr++; } else if (tag == 0xff) { KJ_REQUIRE(ptr < end, "invalid packed data"); size_t words = *ptr++; total += words; size_t bytes = words * sizeof(word); KJ_REQUIRE(end - ptr >= bytes, "invalid packed data"); ptr += bytes; } } return total; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/message.h0000644000175000017500000006216614731420004020435 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include #include #include #include "common.h" #include "layout.h" #include "any.h" CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private class ReaderArena; class BuilderArena; struct CloneImpl; } class StructSchema; class Orphanage; template class Orphan; // ======================================================================================= struct ReaderOptions { // Options controlling how data is read. uint64_t traversalLimitInWords = 8 * 1024 * 1024; // Limits how many total words of data are allowed to be traversed. Traversal is counted when // a new struct or list builder is obtained, e.g. from a get() accessor. This means that calling // the getter for the same sub-struct multiple times will cause it to be double-counted. Once // the traversal limit is reached, an error will be reported. // // This limit exists for security reasons. It is possible for an attacker to construct a message // in which multiple pointers point at the same location. This is technically invalid, but hard // to detect. Using such a message, an attacker could cause a message which is small on the wire // to appear much larger when actually traversed, possibly exhausting server resources leading to // denial-of-service. // // It makes sense to set a traversal limit that is much larger than the underlying message. // Together with sensible coding practices (e.g. trying to avoid calling sub-object getters // multiple times, which is expensive anyway), this should provide adequate protection without // inconvenience. // // The default limit is 64 MiB. This may or may not be a sensible number for any given use case, // but probably at least prevents easy exploitation while also avoiding causing problems in most // typical cases. int nestingLimit = 64; // Limits how deeply-nested a message structure can be, e.g. structs containing other structs or // lists of structs. // // Like the traversal limit, this limit exists for security reasons. Since it is common to use // recursive code to traverse recursive data structures, an attacker could easily cause a stack // overflow by sending a very-deeply-nested (or even cyclic) message, without the message even // being very large. The default limit of 64 is probably low enough to prevent any chance of // stack overflow, yet high enough that it is never a problem in practice. }; class MessageReader { // Abstract interface for an object used to read a Cap'n Proto message. Subclasses of // MessageReader are responsible for reading the raw, flat message content. Callers should // usually call `messageReader.getRoot()` to get a `MyStructType::Reader` // representing the root of the message, then use that to traverse the message content. // // Some common subclasses of `MessageReader` include `SegmentArrayMessageReader`, whose // constructor accepts pointers to the raw data, and `StreamFdMessageReader` (from // `serialize.h`), which reads the message from a file descriptor. One might implement other // subclasses to handle things like reading from shared memory segments, mmap()ed files, etc. public: MessageReader(ReaderOptions options); // It is suggested that subclasses take ReaderOptions as a constructor parameter, but give it a // default value of "ReaderOptions()". The base class constructor doesn't have a default value // in order to remind subclasses that they really need to give the user a way to provide this. virtual ~MessageReader() noexcept(false); virtual kj::ArrayPtr getSegment(uint id) = 0; // Gets the segment with the given ID, or returns null if no such segment exists. This method // will be called at most once for each segment ID. inline const ReaderOptions& getOptions(); // Get the options passed to the constructor. template typename RootType::Reader getRoot(); // Get the root struct of the message, interpreting it as the given struct type. template typename RootType::Reader getRoot(SchemaType schema); // Dynamically interpret the root struct of the message using the given schema (a StructSchema). // RootType in this case must be DynamicStruct, and you must #include to // use this. bool isCanonical(); // Returns whether the message encoded in the reader is in canonical form. size_t sizeInWords(); // Add up the size of all segments. private: ReaderOptions options; #if defined(__EMSCRIPTEN__) || (defined(__APPLE__) && (defined(__ppc__) || defined(__i386__))) static constexpr size_t arenaSpacePadding = 19; #else static constexpr size_t arenaSpacePadding = 18; #endif // Space in which we can construct a ReaderArena. We don't use ReaderArena directly here // because we don't want clients to have to #include arena.h, which itself includes a bunch of // other headers. We don't use a pointer to a ReaderArena because that would require an // extra malloc on every message which could be expensive when processing small messages. alignas(8) void* arenaSpace[arenaSpacePadding + sizeof(kj::MutexGuarded) / sizeof(void*)]; bool allocatedArena; _::ReaderArena* arena() { return reinterpret_cast<_::ReaderArena*>(arenaSpace); } AnyPointer::Reader getRootInternal(); }; class MessageBuilder { // Abstract interface for an object used to allocate and build a message. Subclasses of // MessageBuilder are responsible for allocating the space in which the message will be written. // The most common subclass is `MallocMessageBuilder`, but other subclasses may be used to do // tricky things like allocate messages in shared memory or mmap()ed files. // // Creating a new message ususually means allocating a new MessageBuilder (ideally on the stack) // and then calling `messageBuilder.initRoot()` to get a `MyStructType::Builder`. // That, in turn, can be used to fill in the message content. When done, you can call // `messageBuilder.getSegmentsForOutput()` to get a list of flat data arrays containing the // message. public: MessageBuilder(); virtual ~MessageBuilder() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(MessageBuilder); struct SegmentInit { kj::ArrayPtr space; size_t wordsUsed; // Number of words in `space` which are used; the rest are free space in which additional // objects may be allocated. }; explicit MessageBuilder(kj::ArrayPtr segments); // Create a MessageBuilder backed by existing memory. This is an advanced interface that most // people should not use. THIS METHOD IS INSECURE; see below. // // This allows a MessageBuilder to be constructed to modify an in-memory message without first // making a copy of the content. This is especially useful in conjunction with mmap(). // // The contents of each segment must outlive the MessageBuilder, but the SegmentInit array itself // only need outlive the constructor. // // SECURITY: Do not use this in conjunction with untrusted data. This constructor assumes that // the input message is valid. This constructor is designed to be used with data you control, // e.g. an mmap'd file which is owned and accessed by only one program. When reading data you // do not trust, you *must* load it into a Reader and then copy into a Builder as a means of // validating the content. // // WARNING: It is NOT safe to initialize a MessageBuilder in this way from memory that is // currently in use by another MessageBuilder or MessageReader. Other readers/builders will // not observe changes to the segment sizes nor newly-allocated segments caused by allocating // new objects in this message. virtual kj::ArrayPtr allocateSegment(uint minimumSize) = 0; // Allocates an array of at least the given number of zero'd words, throwing an exception or // crashing if this is not possible. It is expected that this method will usually return more // space than requested, and the caller should use that extra space as much as possible before // allocating more. The returned space remains valid at least until the MessageBuilder is // destroyed. // // allocateSegment() is responsible for zeroing the memory before returning. This is required // because otherwise the Cap'n Proto implementation would have to zero the memory anyway, and // many allocators are able to provide already-zero'd memory more efficiently. template typename RootType::Builder initRoot(); // Initialize the root struct of the message as the given struct type. template void setRoot(Reader&& value); // Set the root struct to a deep copy of the given struct. template typename RootType::Builder getRoot(); // Get the root struct of the message, interpreting it as the given struct type. template typename RootType::Builder getRoot(SchemaType schema); // Dynamically interpret the root struct of the message using the given schema (a StructSchema). // RootType in this case must be DynamicStruct, and you must #include to // use this. template typename RootType::Builder initRoot(SchemaType schema); // Dynamically init the root struct of the message using the given schema (a StructSchema). // RootType in this case must be DynamicStruct, and you must #include to // use this. template void adoptRoot(Orphan&& orphan); // Like setRoot() but adopts the orphan without copying. kj::ArrayPtr> getSegmentsForOutput(); // Get the raw data that makes up the message. Orphanage getOrphanage(); bool isCanonical(); // Check whether the message builder is in canonical form size_t sizeInWords(); // Add up the allocated space from all segments. private: alignas(8) void* arenaSpace[22]; // Space in which we can construct a BuilderArena. We don't use BuilderArena directly here // because we don't want clients to have to #include arena.h, which itself includes a bunch of // big STL headers. We don't use a pointer to a BuilderArena because that would require an // extra malloc on every message which could be expensive when processing small messages. bool allocatedArena = false; // We have to initialize the arena lazily because when we do so we want to allocate the root // pointer immediately, and this will allocate a segment, which requires a virtual function // call on the MessageBuilder. We can't do such a call in the constructor since the subclass // isn't constructed yet. This is kind of annoying because it means that getOrphanage() is // not thread-safe, but that shouldn't be a huge deal... _::BuilderArena* arena() { return reinterpret_cast<_::BuilderArena*>(arenaSpace); } _::SegmentBuilder* getRootSegment(); AnyPointer::Builder getRootInternal(); kj::Own<_::CapTableBuilder> releaseBuiltinCapTable(); // Hack for clone() to extract the cap table. friend struct _::CloneImpl; // We can't declare clone() as a friend directly because old versions of GCC incorrectly demand // that the first declaration (even if it is a friend declaration) specify the default type args, // whereas correct compilers do not permit default type args to be specified on a friend decl. }; template typename RootType::Reader readMessageUnchecked(const word* data); // IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP, // MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT // USE UNLESS YOU UNDERSTAND THE CONSEQUENCES. // // Given a pointer to a known-valid message located in a single contiguous memory segment, // returns a reader for that message. No bounds-checking will be done while traversing this // message. Use this only if you have already verified that all pointers are valid and in-bounds, // and there are no far pointers in the message. // // To create a message that can be passed to this function, build a message using a MallocAllocator // whose preferred segment size is larger than the message size. This guarantees that the message // will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word // array. That word array is your message; you may pass a pointer to its first word into // readMessageUnchecked() to read the message. // // This can be particularly handy for embedding messages in generated code: you can // embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way // default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have // a message MyMessage, you can read its default value like so: // MyMessage::Reader reader = Message::readMessageUnchecked(MyMessage::DEFAULT.words); // // To sanitize a message from an untrusted source such that it can be safely passed to // readMessageUnchecked(), use copyToUnchecked(). template void copyToUnchecked(Reader&& reader, kj::ArrayPtr uncheckedBuffer); // Copy the content of the given reader into the given buffer, such that it can safely be passed to // readMessageUnchecked(). The buffer's size must be exactly reader.totalSizeInWords() + 1, // otherwise an exception will be thrown. The buffer must be zero'd before calling. template typename RootType::Reader readDataStruct(kj::ArrayPtr data); // Interprets the given data as a single, data-only struct. Only primitive fields (booleans, // numbers, and enums) will be readable; all pointers will be null. This is useful if you want // to use Cap'n Proto as a language/platform-neutral way to pack some bits. // // The input is a word array rather than a byte array to enforce alignment. If you have a byte // array which you know is word-aligned (or if your platform supports unaligned reads and you don't // mind the performance penalty), then you can use `reinterpret_cast` to convert a byte array into // a word array: // // kj::arrayPtr(reinterpret_cast(bytes.begin()), // reinterpret_cast(bytes.end())) template typename kj::ArrayPtr writeDataStruct(BuilderType builder); // Given a struct builder, get the underlying data section as a word array, suitable for passing // to `readDataStruct()`. // // Note that you may call `.toBytes()` on the returned value to convert to `ArrayPtr`. template static typename Type::Reader defaultValue(); // Get a default instance of the given struct or list type. // // TODO(cleanup): Find a better home for this function? template > kj::Own> clone(Reader&& reader); // Make a deep copy of the given Reader on the heap, producing an owned pointer. // ======================================================================================= class SegmentArrayMessageReader: public MessageReader { // A simple MessageReader that reads from an array of word arrays representing all segments. // In particular you can read directly from the output of MessageBuilder::getSegmentsForOutput() // (although it would probably make more sense to call builder.getRoot().asReader() in that case). public: SegmentArrayMessageReader(kj::ArrayPtr> segments, ReaderOptions options = ReaderOptions()); // Creates a message pointing at the given segment array, without taking ownership of the // segments. All arrays passed in must remain valid until the MessageReader is destroyed. KJ_DISALLOW_COPY_AND_MOVE(SegmentArrayMessageReader); ~SegmentArrayMessageReader() noexcept(false); virtual kj::ArrayPtr getSegment(uint id) override; private: kj::ArrayPtr> segments; }; enum class AllocationStrategy: uint8_t { FIXED_SIZE, // The builder will prefer to allocate the same amount of space for each segment with no // heuristic growth. It will still allocate larger segments when the preferred size is too small // for some single object. This mode is generally not recommended, but can be particularly useful // for testing in order to force a message to allocate a predictable number of segments. Note // that you can force every single object in the message to be located in a separate segment by // using this mode with firstSegmentWords = 0. GROW_HEURISTICALLY // The builder will heuristically decide how much space to allocate for each segment. Each // allocated segment will be progressively larger than the previous segments on the assumption // that message sizes are exponentially distributed. The total number of segments that will be // allocated for a message of size n is O(log n). }; constexpr uint SUGGESTED_FIRST_SEGMENT_WORDS = 1024; constexpr AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY = AllocationStrategy::GROW_HEURISTICALLY; class MallocMessageBuilder: public MessageBuilder { // A simple MessageBuilder that uses malloc() (actually, calloc()) to allocate segments. This // implementation should be reasonable for any case that doesn't require writing the message to // a specific location in memory. public: explicit MallocMessageBuilder(uint firstSegmentWords = SUGGESTED_FIRST_SEGMENT_WORDS, AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY); // Creates a BuilderContext which allocates at least the given number of words for the first // segment, and then uses the given strategy to decide how much to allocate for subsequent // segments. When choosing a value for firstSegmentWords, consider that: // 1) Reading and writing messages gets slower when multiple segments are involved, so it's good // if most messages fit in a single segment. // 2) Unused bytes will not be written to the wire, so generally it is not a big deal to allocate // more space than you need. It only becomes problematic if you are allocating many messages // in parallel and thus use lots of memory, or if you allocate so much extra space that just // zeroing it out becomes a bottleneck. // The defaults have been chosen to be reasonable for most people, so don't change them unless you // have reason to believe you need to. explicit MallocMessageBuilder(kj::ArrayPtr firstSegment, AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY); // This version always returns the given array for the first segment, and then proceeds with the // allocation strategy. This is useful for optimization when building lots of small messages in // a tight loop: you can reuse the space for the first segment. // // firstSegment MUST be zero-initialized. MallocMessageBuilder's destructor will write new zeros // over any space that was used so that it can be reused. KJ_DISALLOW_COPY_AND_MOVE(MallocMessageBuilder); virtual ~MallocMessageBuilder() noexcept(false); virtual kj::ArrayPtr allocateSegment(uint minimumSize) override; private: uint nextSize; AllocationStrategy allocationStrategy; bool ownFirstSegment; bool returnedFirstSegment; void* firstSegment; kj::Vector moreSegments; }; class FlatMessageBuilder: public MessageBuilder { // THIS IS NOT THE CLASS YOU'RE LOOKING FOR. // // If you want to write a message into already-existing scratch space, use `MallocMessageBuilder` // and pass the scratch space to its constructor. It will then only fall back to malloc() if // the scratch space is not large enough. // // Do NOT use this class unless you really know what you're doing. This class is problematic // because it requires advance knowledge of the size of your message, which is usually impossible // to determine without actually building the message. The class was created primarily to // implement `copyToUnchecked()`, which itself exists only to support other internal parts of // the Cap'n Proto implementation. public: explicit FlatMessageBuilder(kj::ArrayPtr array); KJ_DISALLOW_COPY_AND_MOVE(FlatMessageBuilder); virtual ~FlatMessageBuilder() noexcept(false); void requireFilled(); // Throws an exception if the flat array is not exactly full. virtual kj::ArrayPtr allocateSegment(uint minimumSize) override; private: kj::ArrayPtr array; bool allocated; }; // ======================================================================================= // implementation details inline const ReaderOptions& MessageReader::getOptions() { return options; } template inline typename RootType::Reader MessageReader::getRoot() { return getRootInternal().getAs(); } template inline typename RootType::Builder MessageBuilder::initRoot() { return getRootInternal().initAs(); } template inline void MessageBuilder::setRoot(Reader&& value) { getRootInternal().setAs>(value); } template inline typename RootType::Builder MessageBuilder::getRoot() { return getRootInternal().getAs(); } template void MessageBuilder::adoptRoot(Orphan&& orphan) { return getRootInternal().adopt(kj::mv(orphan)); } template typename RootType::Reader MessageReader::getRoot(SchemaType schema) { return getRootInternal().getAs(schema); } template typename RootType::Builder MessageBuilder::getRoot(SchemaType schema) { return getRootInternal().getAs(schema); } template typename RootType::Builder MessageBuilder::initRoot(SchemaType schema) { return getRootInternal().initAs(schema); } template typename RootType::Reader readMessageUnchecked(const word* data) { return AnyPointer::Reader(_::PointerReader::getRootUnchecked(data)).getAs(); } template void copyToUnchecked(Reader&& reader, kj::ArrayPtr uncheckedBuffer) { FlatMessageBuilder builder(uncheckedBuffer); builder.setRoot(kj::fwd(reader)); builder.requireFilled(); } template typename RootType::Reader readDataStruct(kj::ArrayPtr data) { return typename RootType::Reader(_::StructReader(data)); } template typename kj::ArrayPtr writeDataStruct(BuilderType builder) { auto bytes = _::PointerHelpers>::getInternalBuilder(kj::mv(builder)) .getDataSectionAsBlob(); return kj::arrayPtr(reinterpret_cast(bytes.begin()), reinterpret_cast(bytes.end())); } template static typename Type::Reader defaultValue() { return typename Type::Reader(_::StructReader()); } namespace _ { struct CloneImpl { static inline kj::Own<_::CapTableBuilder> releaseBuiltinCapTable(MessageBuilder& message) { return message.releaseBuiltinCapTable(); } }; }; template kj::Own> clone(Reader&& reader) { auto size = reader.totalSize(); auto buffer = kj::heapArray(size.wordCount + 1); memset(buffer.asBytes().begin(), 0, buffer.asBytes().size()); if (size.capCount == 0) { copyToUnchecked(reader, buffer); auto result = readMessageUnchecked>(buffer.begin()); return kj::attachVal(result, kj::mv(buffer)); } else { FlatMessageBuilder builder(buffer); builder.setRoot(kj::fwd(reader)); builder.requireFilled(); auto capTable = _::CloneImpl::releaseBuiltinCapTable(builder); AnyPointer::Reader raw(_::PointerReader::getRootUnchecked(buffer.begin()).imbue(capTable)); return kj::attachVal(raw.getAs>(), kj::mv(buffer), kj::mv(capTable)); } } template kj::Array canonicalize(T&& reader) { return _::PointerHelpers>::getInternalReader(reader).canonicalize(); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/test.capnp0000644000175000017500000007310014712011043020626 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xd508eebdc2dc42b8; using Cxx = import "c++.capnp"; # Use a namespace likely to cause trouble if the generated code doesn't use fully-qualified # names for stuff in the capnproto namespace. $Cxx.namespace("capnproto_test::capnp::test"); enum TestEnum { foo @0; bar @1; baz @2; qux @3; quux @4; corge @5; grault @6; garply @7; } struct TestAllTypes { voidField @0 : Void; boolField @1 : Bool; int8Field @2 : Int8; int16Field @3 : Int16; int32Field @4 : Int32; int64Field @5 : Int64; uInt8Field @6 : UInt8; uInt16Field @7 : UInt16; uInt32Field @8 : UInt32; uInt64Field @9 : UInt64; float32Field @10 : Float32; float64Field @11 : Float64; textField @12 : Text; dataField @13 : Data; structField @14 : TestAllTypes; enumField @15 : TestEnum; interfaceField @16 : Void; # TODO voidList @17 : List(Void); boolList @18 : List(Bool); int8List @19 : List(Int8); int16List @20 : List(Int16); int32List @21 : List(Int32); int64List @22 : List(Int64); uInt8List @23 : List(UInt8); uInt16List @24 : List(UInt16); uInt32List @25 : List(UInt32); uInt64List @26 : List(UInt64); float32List @27 : List(Float32); float64List @28 : List(Float64); textList @29 : List(Text); dataList @30 : List(Data); structList @31 : List(TestAllTypes); enumList @32 : List(TestEnum); interfaceList @33 : List(Void); # TODO } struct TestDefaults { voidField @0 : Void = void; boolField @1 : Bool = true; int8Field @2 : Int8 = -123; int16Field @3 : Int16 = -12345; int32Field @4 : Int32 = -12345678; int64Field @5 : Int64 = -123456789012345; uInt8Field @6 : UInt8 = 234; uInt16Field @7 : UInt16 = 45678; uInt32Field @8 : UInt32 = 3456789012; uInt64Field @9 : UInt64 = 12345678901234567890; float32Field @10 : Float32 = 1234.5; float64Field @11 : Float64 = -123e45; textField @12 : Text = "foo"; dataField @13 : Data = 0x"62 61 72"; # "bar" structField @14 : TestAllTypes = ( voidField = void, boolField = true, int8Field = -12, int16Field = 3456, int32Field = -78901234, int64Field = 56789012345678, uInt8Field = 90, uInt16Field = 1234, uInt32Field = 56789012, uInt64Field = 345678901234567890, float32Field = -1.25e-10, float64Field = 345, textField = "baz", dataField = "qux", structField = ( textField = "nested", structField = (textField = "really nested")), enumField = baz, # interfaceField can't have a default voidList = [void, void, void], boolList = [false, true, false, true, true], int8List = [12, -34, -0x80, 0x7f], int16List = [1234, -5678, -0x8000, 0x7fff], int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], uInt8List = [12, 34, 0, 0xff], uInt16List = [1234, 5678, 0, 0xffff], uInt32List = [12345678, 90123456, 0, 0xffffffff], uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], textList = ["quux", "corge", "grault"], dataList = ["garply", "waldo", "fred"], structList = [ (textField = "x " "structlist" " 1"), (textField = "x structlist 2"), (textField = "x structlist 3")], enumList = [qux, bar, grault] # interfaceList can't have a default ); enumField @15 : TestEnum = corge; interfaceField @16 : Void; # TODO voidList @17 : List(Void) = [void, void, void, void, void, void]; boolList @18 : List(Bool) = [true, false, false, true]; int8List @19 : List(Int8) = [111, -111]; int16List @20 : List(Int16) = [11111, -11111]; int32List @21 : List(Int32) = [111111111, -111111111]; int64List @22 : List(Int64) = [1111111111111111111, -1111111111111111111]; uInt8List @23 : List(UInt8) = [111, 222] ; uInt16List @24 : List(UInt16) = [33333, 44444]; uInt32List @25 : List(UInt32) = [3333333333]; uInt64List @26 : List(UInt64) = [11111111111111111111]; float32List @27 : List(Float32) = [5555.5, inf, -inf, nan]; float64List @28 : List(Float64) = [7777.75, inf, -inf, nan]; textList @29 : List(Text) = ["plugh", "xyzzy", "thud"]; dataList @30 : List(Data) = ["oops", "exhausted", "rfc3092"]; structList @31 : List(TestAllTypes) = [ (textField = "structlist 1"), (textField = "structlist 2"), (textField = "structlist 3")]; enumList @32 : List(TestEnum) = [foo, garply]; interfaceList @33 : List(Void); # TODO } struct TestAnyPointer { anyPointerField @0 :AnyPointer; # Do not add any other fields here! Some tests rely on anyPointerField being the last pointer # in the struct. } struct TestAnyOthers { anyStructField @0 :AnyStruct; anyListField @1 :AnyList; capabilityField @2 :Capability; } struct TestOutOfOrder { foo @3 :Text; bar @2 :Text; baz @8 :Text; qux @0 :Text; quux @6 :Text; corge @4 :Text; grault @1 :Text; garply @7 :Text; waldo @5 :Text; } struct TestUnion { union0 @0! :union { # Pack union 0 under ideal conditions: there is no unused padding space prior to it. u0f0s0 @4: Void; u0f0s1 @5: Bool; u0f0s8 @6: Int8; u0f0s16 @7: Int16; u0f0s32 @8: Int32; u0f0s64 @9: Int64; u0f0sp @10: Text; # Pack more stuff into union0 -- should go in same space. u0f1s0 @11: Void; u0f1s1 @12: Bool; u0f1s8 @13: Int8; u0f1s16 @14: Int16; u0f1s32 @15: Int32; u0f1s64 @16: Int64; u0f1sp @17: Text; } # Pack one bit in order to make pathological situation for union1. bit0 @18: Bool; union1 @1! :union { # Pack pathologically bad case. Each field takes up new space. u1f0s0 @19: Void; u1f0s1 @20: Bool; u1f1s1 @21: Bool; u1f0s8 @22: Int8; u1f1s8 @23: Int8; u1f0s16 @24: Int16; u1f1s16 @25: Int16; u1f0s32 @26: Int32; u1f1s32 @27: Int32; u1f0s64 @28: Int64; u1f1s64 @29: Int64; u1f0sp @30: Text; u1f1sp @31: Text; # Pack more stuff into union1 -- each should go into the same space as corresponding u1f0s*. u1f2s0 @32: Void; u1f2s1 @33: Bool; u1f2s8 @34: Int8; u1f2s16 @35: Int16; u1f2s32 @36: Int32; u1f2s64 @37: Int64; u1f2sp @38: Text; } # Fill in the rest of that bitfield from earlier. bit2 @39: Bool; bit3 @40: Bool; bit4 @41: Bool; bit5 @42: Bool; bit6 @43: Bool; bit7 @44: Bool; # Interleave two unions to be really annoying. # Also declare in reverse order to make sure union discriminant values are sorted by field number # and not by declaration order. union2 @2! :union { u2f0s64 @54: Int64; u2f0s32 @52: Int32; u2f0s16 @50: Int16; u2f0s8 @47: Int8; u2f0s1 @45: Bool; } union3 @3! :union { u3f0s64 @55: Int64; u3f0s32 @53: Int32; u3f0s16 @51: Int16; u3f0s8 @48: Int8; u3f0s1 @46: Bool; } byte0 @49: UInt8; } struct TestUnnamedUnion { before @0 :Text; union { foo @1 :UInt16; bar @3 :UInt32; } middle @2 :UInt16; after @4 :Text; } struct TestUnionInUnion { # There is no reason to ever do this. outer :union { inner :union { foo @0 :Int32; bar @1 :Int32; } baz @2 :Int32; } } struct TestGroups { groups :union { foo :group { corge @0 :Int32; grault @2 :Int64; garply @8 :Text; } bar :group { corge @3 :Int32; grault @4 :Text; garply @5 :Int64; } baz :group { corge @1 :Int32; grault @6 :Text; garply @7 :Text; } } } struct TestInterleavedGroups { group1 :group { foo @0 :UInt32; bar @2 :UInt64; union { qux @4 :UInt16; corge :group { grault @6 :UInt64; garply @8 :UInt16; plugh @14 :Text; xyzzy @16 :Text; } fred @12 :Text; } waldo @10 :Text; } group2 :group { foo @1 :UInt32; bar @3 :UInt64; union { qux @5 :UInt16; corge :group { grault @7 :UInt64; garply @9 :UInt16; plugh @15 :Text; xyzzy @17 :Text; } fred @13 :Text; } waldo @11 :Text; } } struct TestUnionDefaults { s16s8s64s8Set @0 :TestUnion = (union0 = (u0f0s16 = 321), union1 = (u1f0s8 = 123), union2 = (u2f0s64 = 12345678901234567), union3 = (u3f0s8 = 55)); s0sps1s32Set @1 :TestUnion = (union0 = (u0f1s0 = void), union1 = (u1f0sp = "foo"), union2 = (u2f0s1 = true), union3 = (u3f0s32 = 12345678)); unnamed1 @2 :TestUnnamedUnion = (foo = 123); unnamed2 @3 :TestUnnamedUnion = (bar = 321, before = "foo", after = "bar"); } struct TestNestedTypes { enum NestedEnum { foo @0; bar @1; } struct NestedStruct { enum NestedEnum { baz @0; qux @1; quux @2; } outerNestedEnum @0 :TestNestedTypes.NestedEnum = bar; innerNestedEnum @1 :NestedEnum = quux; } nestedStruct @0 :NestedStruct; outerNestedEnum @1 :NestedEnum = bar; innerNestedEnum @2 :NestedStruct.NestedEnum = quux; } struct TestUsing { using OuterNestedEnum = TestNestedTypes.NestedEnum; using TestNestedTypes.NestedStruct.NestedEnum; outerNestedEnum @1 :OuterNestedEnum = bar; innerNestedEnum @0 :NestedEnum = quux; } struct TestLists { # Small structs, when encoded as list, will be encoded as primitive lists rather than struct # lists, to save space. struct Struct0 { f @0 :Void; } struct Struct1 { f @0 :Bool; } struct Struct8 { f @0 :UInt8; } struct Struct16 { f @0 :UInt16; } struct Struct32 { f @0 :UInt32; } struct Struct64 { f @0 :UInt64; } struct StructP { f @0 :Text; } # Versions of the above which cannot be encoded as primitive lists. struct Struct0c { f @0 :Void; pad @1 :Text; } struct Struct1c { f @0 :Bool; pad @1 :Text; } struct Struct8c { f @0 :UInt8; pad @1 :Text; } struct Struct16c { f @0 :UInt16; pad @1 :Text; } struct Struct32c { f @0 :UInt32; pad @1 :Text; } struct Struct64c { f @0 :UInt64; pad @1 :Text; } struct StructPc { f @0 :Text; pad @1 :UInt64; } list0 @0 :List(Struct0); list1 @1 :List(Struct1); list8 @2 :List(Struct8); list16 @3 :List(Struct16); list32 @4 :List(Struct32); list64 @5 :List(Struct64); listP @6 :List(StructP); int32ListList @7 :List(List(Int32)); textListList @8 :List(List(Text)); structListList @9 :List(List(TestAllTypes)); } struct TestFieldZeroIsBit { bit @0 :Bool; secondBit @1 :Bool = true; thirdField @2 :UInt8 = 123; } struct TestListDefaults { lists @0 :TestLists = ( list0 = [(f = void), (f = void)], list1 = [(f = true), (f = false), (f = true), (f = true)], list8 = [(f = 123), (f = 45)], list16 = [(f = 12345), (f = 6789)], list32 = [(f = 123456789), (f = 234567890)], list64 = [(f = 1234567890123456), (f = 2345678901234567)], listP = [(f = "foo"), (f = "bar")], int32ListList = [[1, 2, 3], [4, 5], [12341234]], textListList = [["foo", "bar"], ["baz"], ["qux", "corge"]], structListList = [[(int32Field = 123), (int32Field = 456)], [(int32Field = 789)]]); } struct TestLateUnion { # Test what happens if the unions are not the first ordinals in the struct. At one point this # was broken for the dynamic API. foo @0 :Int32; bar @1 :Text; baz @2 :Int16; theUnion @3! :union { qux @4 :Text; corge @5 :List(Int32); grault @6 :Float32; } anotherUnion @7! :union { qux @8 :Text; corge @9 :List(Int32); grault @10 :Float32; } } struct TestOldVersion { # A subset of TestNewVersion. old1 @0 :Int64; old2 @1 :Text; old3 @2 :TestOldVersion; } struct TestNewVersion { # A superset of TestOldVersion. old1 @0 :Int64; old2 @1 :Text; old3 @2 :TestNewVersion; new1 @3 :Int64 = 987; new2 @4 :Text = "baz"; } struct TestOldUnionVersion { union { a @0 :Void; b @1 :UInt64; } } struct TestNewUnionVersion { union { a :union { a0 @0 :Void; a1 @2 :UInt64; } b @1 :UInt64; } } struct TestStructUnion { un @0! :union { struct @1 :SomeStruct; object @2 :TestAnyPointer; } struct SomeStruct { someText @0 :Text; moreText @1 :Text; } } struct TestPrintInlineStructs { someText @0 :Text; structList @1 :List(InlineStruct); struct InlineStruct { int32Field @0 :Int32; textField @1 :Text; } } struct TestWholeFloatDefault { # At one point, these failed to compile in C++ because it would produce literals like "123f", # which is not valid; it needs to be "123.0f". field @0 :Float32 = 123; bigField @1 :Float32 = 2e30; const constant :Float32 = 456; const bigConstant :Float32 = 4e30; } struct TestGenerics(Foo, Bar) { foo @0 :Foo; rev @1 :TestGenerics(Bar, Foo); union { uv @2:Void; ug :group { ugfoo @3:Int32; } } list @4 :List(Inner); # At one time this failed to compile with MSVC due to poor expression SFINAE support. struct Inner { foo @0 :Foo; bar @1 :Bar; } struct Inner2(Baz) { bar @0 :Bar; baz @1 :Baz; innerBound @2 :Inner; innerUnbound @3 :TestGenerics.Inner; struct DeepNest(Qux) { foo @0 :Foo; bar @1 :Bar; baz @2 :Baz; qux @3 :Qux; interface DeepNestInterface(Quux) { # At one time this failed to compile. call @0 () -> (); } } } interface Interface(Qux) { call @0 Inner2(Text) -> (qux :Qux, gen :TestGenerics(TestAllTypes, TestAnyPointer)); } annotation ann(struct) :Foo; using AliasFoo = Foo; using AliasInner = Inner; using AliasInner2 = Inner2; using AliasInner2Text = Inner2(Text); using AliasRev = TestGenerics(Bar, Foo); struct UseAliases { foo @0 :AliasFoo; inner @1 :AliasInner; inner2 @2 :AliasInner2; inner2Bind @3 :AliasInner2(Text); inner2Text @4 :AliasInner2Text; revFoo @5 :AliasRev.AliasFoo; } } struct BoxedText { text @0 :Text; } using BrandedAlias = TestGenerics(BoxedText, Text); struct TestGenericsWrapper(Foo, Bar) { value @0 :TestGenerics(Foo, Bar); } struct TestGenericsWrapper2 { value @0 :TestGenericsWrapper(Text, TestAllTypes); } interface TestImplicitMethodParams { call @0 [T, U] (foo :T, bar :U) -> TestGenerics(T, U); } interface TestImplicitMethodParamsInGeneric(V) { call @0 [T, U] (foo :T, bar :U) -> TestGenerics(T, U); } struct TestGenericsUnion(Foo, Bar) { # At one point this failed to compile. union { foo @0 :Foo; bar @1 :Bar; } } struct TestUseGenerics $TestGenerics(Text, Data).ann("foo") { basic @0 :TestGenerics(TestAllTypes, TestAnyPointer); inner @1 :TestGenerics(TestAllTypes, TestAnyPointer).Inner; inner2 @2 :TestGenerics(TestAllTypes, TestAnyPointer).Inner2(Text); unspecified @3 :TestGenerics; unspecifiedInner @4 :TestGenerics.Inner2(Text); wrapper @8 :TestGenericsWrapper(TestAllTypes, TestAnyPointer); cap @18 :TestGenerics(TestInterface, Text); genericCap @19 :TestGenerics(TestAllTypes, List(UInt32)).Interface(Data); default @5 :TestGenerics(TestAllTypes, Text) = (foo = (int16Field = 123), rev = (foo = "text", rev = (foo = (int16Field = 321)))); defaultInner @6 :TestGenerics(TestAllTypes, Text).Inner = (foo = (int16Field = 123), bar = "text"); defaultUser @7 :TestUseGenerics = (basic = (foo = (int16Field = 123))); defaultWrapper @9 :TestGenericsWrapper(Text, TestAllTypes) = (value = (foo = "text", rev = (foo = (int16Field = 321)))); defaultWrapper2 @10 :TestGenericsWrapper2 = (value = (value = (foo = "text", rev = (foo = (int16Field = 321))))); aliasFoo @11 :TestGenerics(TestAllTypes, TestAnyPointer).AliasFoo = (int16Field = 123); aliasInner @12 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner = (foo = (int16Field = 123)); aliasInner2 @13 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2 = (innerBound = (foo = (int16Field = 123))); aliasInner2Bind @14 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2(List(UInt32)) = (baz = [12, 34], innerBound = (foo = (int16Field = 123))); aliasInner2Text @15 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2Text = (baz = "text", innerBound = (foo = (int16Field = 123))); aliasRev @16 :TestGenerics(TestAnyPointer, Text).AliasRev.AliasFoo = "text"; useAliases @17 :TestGenerics(TestAllTypes, List(UInt32)).UseAliases = ( foo = (int16Field = 123), inner = (foo = (int16Field = 123)), inner2 = (innerBound = (foo = (int16Field = 123))), inner2Bind = (baz = "text", innerBound = (foo = (int16Field = 123))), inner2Text = (baz = "text", innerBound = (foo = (int16Field = 123))), revFoo = [12, 34, 56]); bindEnumList @20 :TestGenerics(List(TestEnum), Text); } struct TestEmptyStruct {} struct TestConstants { const voidConst :Void = void; const boolConst :Bool = true; const int8Const :Int8 = -123; const int16Const :Int16 = -12345; const int32Const :Int32 = -12345678; const int64Const :Int64 = -123456789012345; const uint8Const :UInt8 = 234; const uint16Const :UInt16 = 45678; const uint32Const :UInt32 = 3456789012; const uint64Const :UInt64 = 12345678901234567890; const float32Const :Float32 = 1234.5; const float64Const :Float64 = -123e45; const textConst :Text = "foo"; const dataConst :Data = "bar"; const structConst :TestAllTypes = ( voidField = void, boolField = true, int8Field = -12, int16Field = 3456, int32Field = -78901234, int64Field = 56789012345678, uInt8Field = 90, uInt16Field = 1234, uInt32Field = 56789012, uInt64Field = 345678901234567890, float32Field = -1.25e-10, float64Field = 345, textField = "baz", dataField = "qux", structField = ( textField = "nested", structField = (textField = "really nested")), enumField = baz, # interfaceField can't have a default voidList = [void, void, void], boolList = [false, true, false, true, true], int8List = [12, -34, -0x80, 0x7f], int16List = [1234, -5678, -0x8000, 0x7fff], int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], uInt8List = [12, 34, 0, 0xff], uInt16List = [1234, 5678, 0, 0xffff], uInt32List = [12345678, 90123456, 0, 0xffffffff], uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], textList = ["quux", "corge", "grault"], dataList = ["garply", "waldo", "fred"], structList = [ (textField = "x " "structlist" " 1"), (textField = "x structlist 2"), (textField = "x structlist 3")], enumList = [qux, bar, grault] # interfaceList can't have a default ); const enumConst :TestEnum = corge; const voidListConst :List(Void) = [void, void, void, void, void, void]; const boolListConst :List(Bool) = [true, false, false, true]; const int8ListConst :List(Int8) = [111, -111]; const int16ListConst :List(Int16) = [11111, -11111]; const int32ListConst :List(Int32) = [111111111, -111111111]; const int64ListConst :List(Int64) = [1111111111111111111, -1111111111111111111]; const uint8ListConst :List(UInt8) = [111, 222] ; const uint16ListConst :List(UInt16) = [33333, 44444]; const uint32ListConst :List(UInt32) = [3333333333]; const uint64ListConst :List(UInt64) = [11111111111111111111]; const float32ListConst :List(Float32) = [5555.5, inf, -inf, nan]; const float64ListConst :List(Float64) = [7777.75, inf, -inf, nan]; const textListConst :List(Text) = ["plugh", "xyzzy", "thud"]; const dataListConst :List(Data) = ["oops", "exhausted", "rfc3092"]; const structListConst :List(TestAllTypes) = [ (textField = "structlist 1"), (textField = "structlist 2"), (textField = "structlist 3")]; const enumListConst :List(TestEnum) = [foo, garply]; } const globalInt :UInt32 = 12345; const globalText :Text = "foobar"; const globalStruct :TestAllTypes = (int32Field = 54321); const globalPrintableStruct :TestPrintInlineStructs = (someText = "foo"); const derivedConstant :TestAllTypes = ( uInt32Field = .globalInt, textField = TestConstants.textConst, structField = TestConstants.structConst, int16List = TestConstants.int16ListConst, structList = TestConstants.structListConst); const genericConstant :TestGenerics(TestAllTypes, Text) = (foo = (int16Field = 123), rev = (foo = "text", rev = (foo = (int16Field = 321)))); const embeddedData :Data = embed "testdata/packed"; const embeddedText :Text = embed "testdata/short.txt"; const embeddedStruct :TestAllTypes = embed "testdata/binary"; const nonAsciiText :Text = "♫ é ✓"; const blockText :Text = `foo bar baz `"qux" `corge` 'grault' "regular\"quoted\"line" `garply\nwaldo\tfred\"plugh\"xyzzy\'thud ; struct TestAnyPointerConstants { anyKindAsStruct @0 :AnyPointer; anyStructAsStruct @1 :AnyStruct; anyKindAsList @2 :AnyPointer; anyListAsList @3 :AnyList; } const anyPointerConstants :TestAnyPointerConstants = ( anyKindAsStruct = TestConstants.structConst, anyStructAsStruct = TestConstants.structConst, anyKindAsList = TestConstants.int32ListConst, anyListAsList = TestConstants.int32ListConst, ); struct TestListOfAny { capList @0 :List(Capability); #listList @1 :List(AnyList); # TODO(someday): Make List(AnyList) work correctly in C++ generated code. } interface TestInterface { foo @0 (i :UInt32, j :Bool) -> (x :Text); bar @1 () -> (); baz @2 (s: TestAllTypes); } interface TestExtends extends(TestInterface) { qux @0 (); corge @1 TestAllTypes -> (); grault @2 () -> TestAllTypes; } interface TestExtends2 extends(TestExtends) {} interface TestPipeline { getCap @0 (n: UInt32, inCap :TestInterface) -> (s: Text, outBox :Box); testPointers @1 (cap :TestInterface, obj :AnyPointer, list :List(TestInterface)) -> (); getAnyCap @2 (n: UInt32, inCap :Capability) -> (s: Text, outBox :AnyBox); getCapPipelineOnly @3 () -> (outBox :Box); # Never returns, but uses setPipeline() to make the pipeline work. struct Box { cap @0 :TestInterface; } struct AnyBox { cap @0 :Capability; } } interface TestCallOrder { getCallSequence @0 (expected: UInt32) -> (n: UInt32); # First call returns 0, next returns 1, ... # # The input `expected` is ignored but useful for disambiguating debug logs. } interface TestTailCallee $Cxx.allowCancellation { struct TailResult { i @0 :UInt32; t @1 :Text; c @2 :TestCallOrder; } foo @0 (i :Int32, t :Text) -> TailResult; } interface TestTailCaller { foo @0 (i :Int32, callee :TestTailCallee) -> TestTailCallee.TailResult; } interface TestStreaming $Cxx.allowCancellation { doStreamI @0 (i :UInt32) -> stream; doStreamJ @1 (j :UInt32) -> stream; finishStream @2 () -> (totalI :UInt32, totalJ :UInt32); # Test streaming. finishStream() returns the totals of the values streamed to the other calls. } interface TestHandle {} interface TestMoreStuff extends(TestCallOrder) { # Catch-all type that contains lots of testing methods. callFoo @0 (cap :TestInterface) -> (s: Text); # Call `cap.foo()`, check the result, and return "bar". callFooWhenResolved @1 (cap :TestInterface) -> (s: Text); # Like callFoo but waits for `cap` to resolve first. neverReturn @2 (cap :TestInterface) -> (capCopy :TestInterface) $Cxx.allowCancellation; # Doesn't return. You should cancel it. hold @3 (cap :TestInterface) -> (); # Returns immediately but holds on to the capability. callHeld @4 () -> (s: Text); # Calls the capability previously held using `hold` (and keeps holding it). getHeld @5 () -> (cap :TestInterface); # Returns the capability previously held using `hold` (and keeps holding it). echo @6 (cap :TestCallOrder) -> (cap :TestCallOrder); # Just returns the input cap. expectCancel @7 (cap :TestInterface) -> () $Cxx.allowCancellation; # evalLater()-loops forever, holding `cap`. Must be canceled. methodWithDefaults @8 (a :Text, b :UInt32 = 123, c :Text = "foo") -> (d :Text, e :Text = "bar"); methodWithNullDefault @12 (a :Text, b :TestInterface = null); getHandle @9 () -> (handle :TestHandle); # Get a new handle. Tests have an out-of-band way to check the current number of live handles, so # this can be used to test garbage collection. getNull @10 () -> (nullCap :TestMoreStuff); # Always returns a null capability. getEnormousString @11 () -> (str :Text); # Attempts to return an 100MB string. Should always fail. writeToFd @13 (fdCap1 :TestInterface, fdCap2 :TestInterface) -> (fdCap3 :TestInterface, secondFdPresent :Bool); # Expects fdCap1 and fdCap2 wrap socket file descriptors. Writes "foo" to the first and "bar" to # the second. Also creates a socketpair, writes "baz" to one end, and returns the other end. throwException @14 (); throwRemoteException @15 (); } interface TestMembrane { makeThing @0 () -> (thing :Thing); callPassThrough @1 (thing :Thing, tailCall :Bool) -> Result; callIntercept @2 (thing :Thing, tailCall :Bool) -> Result; loopback @3 (thing :Thing) -> (thing :Thing); waitForever @4 () $Cxx.allowCancellation; interface Thing { passThrough @0 () -> Result; intercept @1 () -> Result; } struct Result { text @0 :Text; } } struct TestContainMembrane { cap @0 :TestMembrane.Thing; list @1 :List(TestMembrane.Thing); } struct TestTransferCap { list @0 :List(Element); struct Element { text @0 :Text; cap @1 :TestInterface; } } interface TestKeywordMethods { delete @0 (); class @1 (); void @2 (); return @3 (); } interface TestAuthenticatedBootstrap(VatId) { getCallerId @0 () -> (caller :VatId); } struct TestSturdyRef { hostId @0 :TestSturdyRefHostId; objectId @1 :AnyPointer; } struct TestSturdyRefHostId { host @0 :Text; } struct TestSturdyRefObjectId { tag @0 :Tag; enum Tag { testInterface @0; testExtends @1; testPipeline @2; testTailCallee @3; testTailCaller @4; testMoreStuff @5; } } struct TestProvisionId {} struct TestRecipientId {} struct TestThirdPartyCapId {} struct TestJoinResult {} struct TestNameAnnotation $Cxx.name("RenamedStruct") { union { badFieldName @0 :Bool $Cxx.name("goodFieldName"); bar @1 :Int8; } enum BadlyNamedEnum $Cxx.name("RenamedEnum") { foo @0; bar @1; baz @2 $Cxx.name("qux"); } anotherBadFieldName @2 :BadlyNamedEnum $Cxx.name("anotherGoodFieldName"); struct NestedStruct $Cxx.name("RenamedNestedStruct") { badNestedFieldName @0 :Bool $Cxx.name("goodNestedFieldName"); anotherBadNestedFieldName @1 :NestedStruct $Cxx.name("anotherGoodNestedFieldName"); enum DeeplyNestedEnum $Cxx.name("RenamedDeeplyNestedEnum") { quux @0; corge @1; grault @2 $Cxx.name("garply"); } } badlyNamedUnion :union $Cxx.name("renamedUnion") { badlyNamedGroup :group $Cxx.name("renamedGroup") { foo @3 :Void; bar @4 :Void; } baz @5 :NestedStruct $Cxx.name("qux"); } } interface TestNameAnnotationInterface $Cxx.name("RenamedInterface") { badlyNamedMethod @0 (badlyNamedParam :UInt8 $Cxx.name("renamedParam")) $Cxx.name("renamedMethod"); } struct TestImpliedFirstField { struct TextStruct { text @0 :Text; i @1 :UInt32 = 321; } textStruct @0 :TextStruct = "foo"; textStructList @1 :List(TextStruct); intGroup :group { i @2 :UInt32; str @3 :Text = "corge"; } } const testImpliedFirstField :TestImpliedFirstField = ( textStruct = "bar", textStructList = ["baz", (text = "qux", i = 123)], intGroup = 123 ); struct TestCycleANoCaps { foo @0 :TestCycleBNoCaps; } struct TestCycleBNoCaps { foo @0 :List(TestCycleANoCaps); bar @1 :TestAllTypes; } struct TestCycleAWithCaps { foo @0 :TestCycleBWithCaps; } struct TestCycleBWithCaps { foo @0 :List(TestCycleAWithCaps); bar @1 :TestInterface; } capnproto-c++-1.1.0/src/capnp/capability.h0000644000175000017500000015553714712011043021135 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #if CAPNP_LITE #error "RPC APIs, including this header, are not available in lite mode." #endif #include #include #include "raw-schema.h" #include "any.h" #include "pointer-helpers.h" CAPNP_BEGIN_HEADER namespace capnp { template class Response; template class RemotePromise: public kj::Promise>, public T::Pipeline { // A Promise which supports pipelined calls. T is typically a struct type. T must declare // an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply // multiply-inherits that type along with Promise>. T::Pipeline must be movable, // but does not need to be copyable (i.e. just like Promise). // // The promise is for an owned pointer so that the RPC system can allocate the MessageReader // itself. public: inline RemotePromise(kj::Promise>&& promise, typename T::Pipeline&& pipeline) : kj::Promise>(kj::mv(promise)), T::Pipeline(kj::mv(pipeline)) {} inline RemotePromise(decltype(nullptr)) : kj::Promise>(nullptr), T::Pipeline(nullptr) {} KJ_DISALLOW_COPY(RemotePromise); RemotePromise(RemotePromise&& other) = default; RemotePromise& operator=(RemotePromise&& other) = default; kj::Promise> dropPipeline() { // Convenience method to convert this into a plain promise. return kj::mv(*this); } static RemotePromise reducePromise(kj::Promise&& promise); // Hook for KJ so that Promise> automatically reduces to RemotePromise. }; class LocalClient; namespace _ { // private extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++ class CapabilityServerSetBase; struct PipelineBuilderPair; } // namespace _ (private) struct Capability { // A capability without type-safe methods. Typed capability clients wrap `Client` and typed // capability servers subclass `Server` to dispatch to the regular, typed methods. class Client; class Server; struct _capnpPrivate { struct IsInterface; static constexpr uint64_t typeId = 0x3; static constexpr Kind kind = Kind::INTERFACE; static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA; static const _::RawBrandedSchema* brand() { return &_::NULL_INTERFACE_SCHEMA.defaultBrand; } }; }; // ======================================================================================= // Capability clients class RequestHook; class ResponseHook; class PipelineHook; class ClientHook; template class RevocableServer; template class Request: public Params::Builder { // A call that hasn't been sent yet. This class extends a Builder for the call's "Params" // structure with a method send() that actually sends it. // // Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have // a method `Request fooRequest()` (as well as a convenience method // `RemotePromise foo(A::Reader a, B::Reader b)`). public: inline Request(typename Params::Builder builder, kj::Own&& hook) : Params::Builder(builder), hook(kj::mv(hook)) {} inline Request(decltype(nullptr)): Params::Builder(nullptr) {} RemotePromise send() KJ_WARN_UNUSED_RESULT; // Send the call and return a promise for the results. typename Results::Pipeline sendForPipeline(); // Send the call in pipeline-only mode. The returned object can be used to make pipelined calls, // but there is no way to wait for the completion of the original call. This allows some // bookkeeping to be skipped under the hood, saving some time. // // Generally, this method should only be used when the caller will immediately make one or more // pipelined calls on the result, and then throw away the pipeline and all pipelined // capabilities. Other uses may run into caveats, such as: // - Normally, calling `whenResolved()` on a pipelined capability would wait for the original RPC // to complete (and possibly other things, if that RPC itself returned a promise capability), // but when using `sendPipelineOnly()`, `whenResolved()` may complete immediately, or never, or // at an arbitrary time. Do not rely on it. // - Normal path shortening may not work with these capabilities. For exmaple, if the caller // forwards a pipelined capability back to the callee's vat, calls made by the callee to that // capability may continue to proxy through the caller. Conversely, if the callee ends up // returning a capability that points back to the caller's vat, calls on the pipelined // capability may continue to proxy through the callee. private: kj::Own hook; friend class Capability::Client; friend struct DynamicCapability; template friend class CallContext; friend class RequestHook; }; template class StreamingRequest: public Params::Builder { // Like `Request` but for streaming requests. public: inline StreamingRequest(typename Params::Builder builder, kj::Own&& hook) : Params::Builder(builder), hook(kj::mv(hook)) {} inline StreamingRequest(decltype(nullptr)): Params::Builder(nullptr) {} kj::Promise send() KJ_WARN_UNUSED_RESULT; private: kj::Own hook; friend class Capability::Client; friend struct DynamicCapability; template friend class CallContext; friend class RequestHook; }; template class Response: public Results::Reader { // A completed call. This class extends a Reader for the call's answer structure. The Response // is move-only -- once it goes out-of-scope, the underlying message will be freed. public: inline Response(typename Results::Reader reader, kj::Own&& hook) : Results::Reader(reader), hook(kj::mv(hook)) {} private: kj::Own hook; template friend class Request; friend class ResponseHook; }; class Capability::Client { // Base type for capability clients. public: typedef Capability Reads; typedef Capability Calls; Client(decltype(nullptr)); // If you need to declare a Client before you have anything to assign to it (perhaps because // the assignment is going to occur in an if/else scope), you can start by initializing it to // `nullptr`. The resulting client is not meant to be called and throws exceptions from all // methods. template ()>> Client(kj::Own&& server); // Make a client capability that wraps the given server capability. The server's methods will // only be executed in the given EventLoop, regardless of what thread calls the client's methods. template ()>> Client(kj::Promise&& promise); // Make a client from a promise for a future client. The resulting client queues calls until the // promise resolves. Client(kj::Exception&& exception); // Make a broken client that throws the given exception from all calls. Client(Client& other); Client& operator=(Client& other); // Copies by reference counting. Warning: This refcounting is not thread-safe. All copies of // the client must remain in one thread. Client(Client&&) = default; Client& operator=(Client&&) = default; // Move constructor avoids reference counting. explicit Client(kj::Own&& hook); // For use by the RPC implementation: Wrap a ClientHook. template typename T::Client castAs(); // Reinterpret the capability as implementing the given interface. Note that no error will occur // here if the capability does not actually implement this interface, but later method calls will // fail. It's up to the application to decide how indicate that additional interfaces are // supported. // // TODO(perf): GCC 4.8 / Clang 3.3: rvalue-qualified version for better performance. template typename T::Client castAs(InterfaceSchema schema); // Dynamic version. `T` must be `DynamicCapability`, and you must `#include `. kj::Promise whenResolved(); // If the capability is actually only a promise, the returned promise resolves once the // capability itself has resolved to its final destination (or propagates the exception if // the capability promise is rejected). This is mainly useful for error-checking in the case // where no calls are being made. There is no reason to wait for this before making calls; if // the capability does not resolve, the call results will propagate the error. struct CallHints { bool noPromisePipelining = false; // Hints that the pipeline part of the VoidPromiseAndPipeline won't be used, so it can be // a bogus object. bool onlyPromisePipeline = false; // Hints that the promise part of the VoidPromiseAndPipeline won't be used, so it can be a // bogus promise. // // This hint is primarily intended to be passed to `ClientHook::call()`. When using // `ClientHook::newCall()`, you would instead indicate the hint by calling the `ResponseHook`'s // `sendForPipeline()` method. The effect of setting `onlyPromisePipeline = true` when invoking // `ClientHook::newCall()` is unspecified; it might cause the returned `Request` to support // only pipelining even when `send()` is called, or it might not. }; Request typelessRequest( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints); // Make a request without knowing the types of the params or results. You specify the type ID // and method number manually. kj::Promise> getFd(); // If the capability's server implemented Capability::Server::getFd() returning non-null, and all // RPC links between the client and server support FD passing, returns a file descriptor pointing // to the same underlying file description as the server did. Returns null if the server provided // no FD or if FD passing was unavailable at some intervening link. // // This returns a Promise to handle the case of an unresolved promise capability, e.g. a // pipelined capability. The promise resolves no later than when the capability settles, i.e. // the same time `whenResolved()` would complete. // // The file descriptor will remain open at least as long as the Capability::Client remains alive. // If you need it to last longer, you will need to `dup()` it. // TODO(someday): method(s) for Join protected: Client() = default; template Request newCall(uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints); template StreamingRequest newStreamingCall(uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints); private: kj::Own hook; static kj::Own makeLocalClient(kj::Own&& server); static kj::Own makeRevocableLocalClient(Capability::Server& server); static void revokeLocalClient(ClientHook& hook); static void revokeLocalClient(ClientHook& hook, kj::Exception&& reason); template friend struct _::PointerHelpers; friend struct DynamicCapability; friend class Orphanage; friend struct DynamicStruct; friend struct DynamicList; template friend struct List; friend class _::CapabilityServerSetBase; friend class ClientHook; template friend class RevocableServer; }; // ======================================================================================= // Capability servers class CallContextHook; template class CallContext: public kj::DisallowConstCopy { // Wrapper around CallContextHook with a specific return type. // // Methods of this class may only be called from within the server's event loop, not from other // threads. // // The CallContext becomes invalid as soon as the call reports completion. public: explicit CallContext(CallContextHook& hook); typename Params::Reader getParams(); // Get the params payload. void releaseParams(); // Release the params payload. getParams() will throw an exception after this is called. // Releasing the params may allow the RPC system to free up buffer space to handle other // requests. Long-running asynchronous methods should try to call this as early as is // convenient. typename Results::Builder getResults(kj::Maybe sizeHint = nullptr); typename Results::Builder initResults(kj::Maybe sizeHint = nullptr); void setResults(typename Results::Reader value); void adoptResults(Orphan&& value); Orphanage getResultsOrphanage(kj::Maybe sizeHint = nullptr); // Manipulate the results payload. The "Return" message (part of the RPC protocol) will // typically be allocated the first time one of these is called. Some RPC systems may // allocate these messages in a limited space (such as a shared memory segment), therefore the // application should delay calling these as long as is convenient to do so (but don't delay // if doing so would require extra copies later). // // `sizeHint` indicates a guess at the message size. This will usually be used to decide how // much space to allocate for the first message segment (don't worry: only space that is actually // used will be sent on the wire). If omitted, the system decides. The message root pointer // should not be included in the size. So, if you are simply going to copy some existing message // directly into the results, just call `.totalSize()` and pass that in. void setPipeline(typename Results::Pipeline&& pipeline); void setPipeline(typename Results::Pipeline& pipeline); // Tells the system where the capabilities in the response will eventually resolve to. This // allows requests that are promise-pipelined on this call's results to continue their journey // to the final destination before this call itself has completed. // // This is particularly useful when forwarding RPC calls to other remote servers, but where a // tail call can't be used. For example, imagine Alice calls `foo()` on Bob. In `foo()`'s // implementation, Bob calls `bar()` on Charlie. `bar()` returns a capability to Bob, and then // `foo()` returns the same capability on to Alice. Now imagine Alice is actually using promise // pipelining in a chain like `foo().getCap().baz()`. The `baz()` call will travel to Bob as a // pipelined call without waiting for `foo()` to return first. But once it gets to Bob, the // message has to patiently wait until `foo()` has completed there, before it can then be // forwarded on to Charlie. It would be better if immediately upon Bob calling `bar()` on // Charlie, then Alice's call to `baz()` could be forwarded to Charlie as a pipelined call, // without waiting for `bar()` to return. This would avoid a network round trip of latency // between Bob and Charlie. // // To solve this problem, Bob takes the pipeline object from the `bar()` call, transforms it into // an appropriate pipeline for a `foo()` call, and passes that to `setPipeline()`. This allows // Alice's pipelined `baz()` call to flow through immediately. The code looks like: // // kj::Promise foo(FooContext context) { // auto barPromise = charlie.barRequest().send(); // // // Set up the final pipeline using pipelined capabilities from `barPromise`. // capnp::PipelineBuilder pipeline; // pipeline.setResultCap(barPromise.getSomeCap()); // context.setPipeline(pipeline.build()); // // // Now actually wait for the results and process them. // return barPromise // .then([context](capnp::Response response) mutable { // auto results = context.initResults(); // // // Make sure to set up the capabilities exactly as we did in the pipeline. // results.setResultCap(response.getSomeCap()); // // // ... do other stuff with the real response ... // }); // } // // Of course, if `foo()` and `bar()` return exactly the same type, and Bob doesn't intend // to do anything with `bar()`'s response except pass it through, then `tailCall()` is a better // choice here. `setPipeline()` is useful when some transformation is needed on the response, // or the middleman needs to inspect the response for some reason. // // Note: This method has an overload that takes an lvalue reference for convenience. This // overload increments the refcount on the underlying PipelineHook -- it does not keep the // reference. // // Note: Capabilities returned by the replacement pipeline MUST either be exactly the same // capabilities as in the final response, or eventually resolve to exactly the same // capabilities, where "exactly the same" means the underlying `ClientHook` object is exactly // the same object by identity. Resolving to some "equivalent" capability is not good enough. template kj::Promise tailCall(Request&& tailRequest); // Resolve the call by making a tail call. `tailRequest` is a request that has been filled in // but not yet sent. The context will send the call, then fill in the results with the result // of the call. If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called. // // The RPC implementation may be able to optimize a tail call to another machine such that the // results never actually pass through this machine. Even if no such optimization is possible, // `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site. // // In general, this should be the last thing a method implementation calls, and the promise // returned from `tailCall()` should then be returned by the method implementation. void allowCancellation() KJ_UNAVAILABLE( "As of Cap'n Proto 1.0, allowCancellation must be applied statically using an " "annotation in the schema. See annotations defined in /capnp/c++.capnp. For " "DynamicCapability::Server, use the constructor option (the annotation does not apply " "to DynamicCapability). This change was made to gain a significant performance boost -- " "dynamically allowing cancellation required excessive bookkeeping."); private: CallContextHook* hook; friend class Capability::Server; friend struct DynamicCapability; friend class CallContextHook; }; template class StreamingCallContext: public kj::DisallowConstCopy { // Like CallContext but for streaming calls. public: explicit StreamingCallContext(CallContextHook& hook); typename Params::Reader getParams(); void releaseParams(); // Note: tailCall() is not supported because: // - It would significantly complicate the implementation of streaming. // - It wouldn't be particularly useful since streaming calls don't return anything, and they // already compensate for latency. void allowCancellation() KJ_UNAVAILABLE( "As of Cap'n Proto 1.0, allowCancellation must be applied statically using an " "annotation in the schema. See annotations defined in /capnp/c++.capnp. For " "DynamicCapability::Server, use the constructor option (the annotation does not apply " "to DynamicCapability). This change was made to gain a significant performance boost -- " "dynamically allowing cancellation required excessive bookkeeping."); private: CallContextHook* hook; friend class Capability::Server; friend struct DynamicCapability; friend class CallContextHook; }; class Capability::Server { // Objects implementing a Cap'n Proto interface must subclass this. Typically, such objects // will instead subclass a typed Server interface which will take care of implementing // dispatchCall(). public: typedef Capability Serves; struct DispatchCallResult { kj::Promise promise; // Promise for completion of the call. bool isStreaming; // If true, this method was declared as `-> stream;`. No other calls should be permitted until // this call finishes, and if this call throws an exception, all future calls will throw the // same exception. bool allowCancellation = false; // If true, the call can be canceled normally. If false, the immediate caller is responsible // for ensuring that cancellation is prevented and that `context` remains valid until the // call completes normally. // // See the `allowCancellation` annotation defined in `c++.capnp`. }; virtual DispatchCallResult dispatchCall(uint64_t interfaceId, uint16_t methodId, CallContext context) = 0; // Call the given method. `params` is the input struct, and should be released as soon as it // is no longer needed. `context` may be used to allocate the output struct and other call // logistics. virtual kj::Maybe getFd() { return nullptr; } // If this capability is backed by a file descriptor that is safe to directly expose to clients, // returns that FD. When FD passing has been enabled in the RPC layer, this FD may be sent to // other processes along with the capability. virtual kj::Maybe> shortenPath(); // If this returns non-null, then it is a promise which, when resolved, points to a new // capability to which future calls can be sent. Use this in cases where an object implementation // might discover a more-optimized path some time after it starts. // // Implementing this (and returning non-null) will cause the capability to be advertised as a // promise at the RPC protocol level. Once the promise returned by shortenPath() resolves, the // remote client will receive a `Resolve` message updating it to point at the new destination. // // `shortenPath()` can also be used as a hack to shut up the client. If shortenPath() returns // a promise that resolves to an exception, then the client will be notified that the capability // is now broken. Assuming the client is using a correct RPC implemnetation, this should cause // all further calls initiated by the client to this capability to immediately fail client-side, // sparing the server's bandwidth. // // The default implementation always returns nullptr. // TODO(someday): Method which can optionally be overridden to implement Join when the object is // a proxy. protected: inline Capability::Client thisCap(); // Get a capability pointing to this object, much like the `this` keyword. // // The effect of this method is undefined if: // - No capability client has been created pointing to this object. (This is always the case in // the server's constructor.) // - The capability client pointing at this object has been destroyed. (This is always the case // in the server's destructor.) // - The capability client pointing at this object has been revoked using RevocableServer. // - Multiple capability clients have been created around the same server (possible if the server // is refcounted, which is not recommended since the client itself provides refcounting). template CallContext internalGetTypedContext( CallContext typeless); template StreamingCallContext internalGetTypedStreamingContext( CallContext typeless); DispatchCallResult internalUnimplemented(const char* actualInterfaceName, uint64_t requestedTypeId); DispatchCallResult internalUnimplemented(const char* interfaceName, uint64_t typeId, uint16_t methodId); kj::Promise internalUnimplemented(const char* interfaceName, const char* methodName, uint64_t typeId, uint16_t methodId); private: ClientHook* thisHook = nullptr; friend class LocalClient; }; template class RevocableServer { // Allows you to create a capability client pointing to a capability server without taking // ownership of the server. When `RevocableServer` is destroyed, all clients created through it // will become broken. All outstanding RPCs via those clients will be canceled and all future // RPCs will immediately throw. Hence, once the `RevocableServer` is destroyed, it is safe // to destroy the server object it referenced. // // This is particularly useful when you want to create a capability server that points to an // object that you do not own, and thus cannot keep alive beyond some defined lifetime. Since // you cannot force the client to respect lifetime rules, you should use a RevocableServer to // revoke access before the lifetime ends. // // The RevocableServer object can be moved (as long as the server outlives it). public: RevocableServer(typename T::Server& server); RevocableServer(RevocableServer&&) = default; RevocableServer& operator=(RevocableServer&&) = default; ~RevocableServer() noexcept(false); KJ_DISALLOW_COPY(RevocableServer); typename T::Client getClient(); void revoke(); void revoke(kj::Exception&& reason); // Revokes the capability immediately, rather than waiting for the destructor. This can also // be used to specify a custom exception to use when revoking. private: kj::Own hook; }; // ======================================================================================= template class PipelineBuilder: public T::Builder { // Convenience class to build a Pipeline object for use with CallContext::setPipeline(). // // Building a pipeline object is like building an RPC result message, except that you only need // to fill in the capabilities, since the purpose is only to allow pipelined RPC requests to // flow through. // // See the docs for `CallContext::setPipeline()` for an example. public: PipelineBuilder(uint firstSegmentWords = 64); // Construct a builder, allocating the given number of words for the first segment of the backing // message. Since `PipelineBuilder` is typically used with small RPC messages, the default size // here is considerably smaller than with MallocMessageBuilder. typename T::Pipeline build(); // Constructs a `Pipeline` object backed by the current content of this builder. Calling this // consumes the `PipelineBuilder`; no further methods can be invoked. private: kj::Own hook; PipelineBuilder(_::PipelineBuilderPair pair); }; // ======================================================================================= class ReaderCapabilityTable: private _::CapTableReader { // Class which imbues Readers with the ability to read capabilities. // // In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into // an external table. Since these pointers fundamentally point outside the message, a // MessageReader by default has no idea what they point at, and therefore reading capabilities // from such a reader will throw exceptions. // // In order to be able to read capabilities, you must first attach a capability table, using // this class. By "imbuing" a Reader, you get a new Reader which will interpret capability // pointers by treating them as indexes into the ReaderCapabilityTable. // // Note that when using Cap'n Proto's RPC system, this is handled automatically. public: explicit ReaderCapabilityTable(kj::Array>> table); KJ_DISALLOW_COPY_AND_MOVE(ReaderCapabilityTable); template T imbue(T reader); // Return a reader equivalent to `reader` except that when reading capability-valued fields, // the capabilities are looked up in this table. private: kj::Array>> table; kj::Maybe> extractCap(uint index) override; }; class BuilderCapabilityTable: private _::CapTableBuilder { // Class which imbues Builders with the ability to read and write capabilities. // // This is much like ReaderCapabilityTable, except for builders. The table starts out empty, // but capabilities can be added to it over time. public: BuilderCapabilityTable(); KJ_DISALLOW_COPY_AND_MOVE(BuilderCapabilityTable); inline kj::ArrayPtr>> getTable() { return table; } template T imbue(T builder); // Return a builder equivalent to `builder` except that when reading capability-valued fields, // the capabilities are looked up in this table. private: kj::Vector>> table; kj::Maybe> extractCap(uint index) override; uint injectCap(kj::Own&& cap) override; void dropCap(uint index) override; }; // ======================================================================================= namespace _ { // private class CapabilityServerSetBase { public: Capability::Client addInternal(kj::Own&& server, void* ptr); kj::Promise getLocalServerInternal(Capability::Client& client); }; } // namespace _ (private) template class CapabilityServerSet: private _::CapabilityServerSetBase { // Allows a server to recognize its own capabilities when passed back to it, and obtain the // underlying Server objects associated with them. // // All objects in the set must have the same interface type T. The objects may implement various // interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects), // but note that if you compile with RTTI disabled then you will not be able to down-cast through // virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI // disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type, // and you server class will need to be directly derived from that, so that you can use // static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile // with RTTI, then you can freely dynamic_cast and ignore this issue!) public: CapabilityServerSet() = default; KJ_DISALLOW_COPY_AND_MOVE(CapabilityServerSet); typename T::Client add(kj::Own&& server); // Create a new capability Client for the given Server and also add this server to the set. kj::Promise> getLocalServer(typename T::Client& client); // Given a Client pointing to a server previously passed to add(), return the corresponding // Server. This returns a promise because if the input client is itself a promise, this must // wait for it to resolve. Keep in mind that the server will be deleted when all clients are // gone, so the caller should make sure to keep the client alive (hence why this method only // accepts an lvalue input). }; // ======================================================================================= // Hook interfaces which must be implemented by the RPC system. Applications never call these // directly; the RPC system implements them and the types defined earlier in this file wrap them. class RequestHook { // Hook interface implemented by RPC system representing a request being built. public: virtual RemotePromise send() = 0; // Send the call and return a promise for the result. virtual kj::Promise sendStreaming() = 0; // Send a streaming call. virtual AnyPointer::Pipeline sendForPipeline() = 0; // Send a call for pipelining purposes only. virtual const void* getBrand() = 0; // Returns a void* that identifies who made this request. This can be used by an RPC adapter to // discover when tail call is going to be sent over its own connection and therefore can be // optimized into a remote tail call. template inline static kj::Own from(Request&& request) { return kj::mv(request.hook); } }; class ResponseHook { // Hook interface implemented by RPC system representing a response. // // At present this class has no methods. It exists only for garbage collection -- when the // ResponseHook is destroyed, the results can be freed. public: virtual ~ResponseHook() noexcept(false); // Just here to make sure the type is dynamic. template inline static kj::Own from(Response&& response) { return kj::mv(response.hook); } }; // class PipelineHook is declared in any.h because it is needed there. class ClientHook { public: ClientHook(); using CallHints = Capability::Client::CallHints; virtual Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) = 0; // Start a new call, allowing the client to allocate request/response objects as it sees fit. // This version is used when calls are made from application code in the local process. struct VoidPromiseAndPipeline { kj::Promise promise; kj::Own pipeline; }; virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) = 0; // Call the object, but the caller controls allocation of the request/response objects. If the // callee insists on allocating these objects itself, it must make a copy. This version is used // when calls come in over the network via an RPC system. Note that even if the returned // `Promise` is discarded, the call may continue executing if any pipelined calls are // waiting for it. // // The call must not begin synchronously; the callee must arrange for the call to begin in a // later turn of the event loop. Otherwise, application code may call back and affect the // callee's state in an unexpected way. virtual kj::Maybe getResolved() = 0; // If this ClientHook is a promise that has already resolved, returns the inner, resolved version // of the capability. The caller may permanently replace this client with the resolved one if // desired. Returns null if the client isn't a promise or hasn't resolved yet -- use // `whenMoreResolved()` to distinguish between them. // // Once a particular ClientHook's `getResolved()` returns non-null, it must permanently return // exactly the same resolution. This is why `getResolved()` returns a reference -- it is assumed // this object must have a strong reference to the resolution which it intends to keep // permanently, therefore the returned reference will live at least as long as this `ClientHook`. // This "only one resolution" policy is necessary for the RPC system to implement embargoes // properly. virtual kj::Maybe>> whenMoreResolved() = 0; // If this client is a settled reference (not a promise), return nullptr. Otherwise, return a // promise that eventually resolves to a new client that is closer to being the final, settled // client (i.e. the value eventually returned by `getResolved()`). Calling this repeatedly // should eventually produce a settled client. // // Once the promise resolves, `getResolved()` must return exactly the same `ClientHook` as the // one this Promise resolved to. kj::Promise whenResolved(); // Repeatedly calls whenMoreResolved() until it returns nullptr. virtual kj::Own addRef() = 0; // Return a new reference to the same capability. virtual const void* getBrand() = 0; // Returns a void* that identifies who made this client. This can be used by an RPC adapter to // discover when a capability it needs to marshal is one that it created in the first place, and // therefore it can transfer the capability without proxying. static const uint NULL_CAPABILITY_BRAND; static const uint BROKEN_CAPABILITY_BRAND; // Values are irrelevant; used for pointers. inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; } // Returns true if the capability was created as a result of assigning a Client to null or by // reading a null pointer out of a Cap'n Proto message. inline bool isError() { return getBrand() == &BROKEN_CAPABILITY_BRAND; } // Returns true if the capability was created by newBrokenCap(). virtual kj::Maybe getFd() = 0; // Implements Capability::Client::getFd(). If this returns null but whenMoreResolved() returns // non-null, then Capability::Client::getFd() waits for resolution and tries again. static kj::Own from(Capability::Client client) { return kj::mv(client.hook); } }; class RevocableClientHook: public ClientHook { public: virtual void revoke() = 0; virtual void revoke(kj::Exception&& reason) = 0; }; class CallContextHook { // Hook interface implemented by RPC system to manage a call on the server side. See // CallContext. public: virtual AnyPointer::Reader getParams() = 0; virtual void releaseParams() = 0; virtual AnyPointer::Builder getResults(kj::Maybe sizeHint) = 0; virtual kj::Promise tailCall(kj::Own&& request) = 0; virtual void setPipeline(kj::Own&& pipeline) = 0; virtual kj::Promise onTailCall() = 0; // If `tailCall()` is called, resolves to the PipelineHook from the tail call. An // implementation of `ClientHook::call()` is allowed to call this at most once. virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own&& request) = 0; // Call this when you would otherwise call onTailCall() immediately followed by tailCall(). // Implementations of tailCall() should typically call directTailCall() and then fulfill the // promise fulfiller for onTailCall() with the returned pipeline. virtual kj::Own addRef() = 0; template static CallContextHook& from(CallContext& context) { return *context.hook; } template static CallContextHook& from(StreamingCallContext& context) { return *context.hook; } }; kj::Own newLocalPromiseClient(kj::Promise>&& promise); // Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to // the new client. This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the // redirection to the eventual replacement client. kj::Own newLocalPromisePipeline(kj::Promise>&& promise); // Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to // the new pipeline. kj::Own newBrokenCap(kj::StringPtr reason); kj::Own newBrokenCap(kj::Exception&& reason); // Helper function that creates a capability which simply throws exceptions when called. kj::Own newBrokenPipeline(kj::Exception&& reason); // Helper function that creates a pipeline which simply throws exceptions when called. Request newBrokenRequest( kj::Exception&& reason, kj::Maybe sizeHint); // Helper function that creates a Request object that simply throws exceptions when sent. kj::Own getDisabledPipeline(); // Gets a PipelineHook appropriate to use when CallHints::noPromisePipelining is true. This will // throw from all calls. This does not actually allocate the object; a static global object is // returned with a null disposer. // ======================================================================================= // Extend PointerHelpers for interfaces namespace _ { // private template struct PointerHelpers { static inline typename T::Client get(PointerReader reader) { return typename T::Client(reader.getCapability()); } static inline typename T::Client get(PointerBuilder builder) { return typename T::Client(builder.getCapability()); } static inline void set(PointerBuilder builder, typename T::Client&& value) { builder.setCapability(kj::mv(value.Capability::Client::hook)); } static inline void set(PointerBuilder builder, typename T::Client& value) { builder.setCapability(value.Capability::Client::hook->addRef()); } static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } }; } // namespace _ (private) // ======================================================================================= // Extend List for interfaces template struct List { List() = delete; class Reader { public: typedef List Reads; Reader() = default; inline explicit Reader(_::ListReader reader): reader(reader) {} inline uint size() const { return unbound(reader.size() / ELEMENTS); } inline typename T::Client operator[](uint index) const { KJ_IREQUIRE(index < size()); return typename T::Client(reader.getPointerElement( bounded(index) * ELEMENTS).getCapability()); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } private: _::ListReader reader; template friend struct _::PointerHelpers; template friend struct List; friend class Orphanage; template friend struct ToDynamic_; }; class Builder { public: typedef List Builds; Builder() = delete; inline Builder(decltype(nullptr)) {} inline explicit Builder(_::ListBuilder builder): builder(builder) {} inline operator Reader() const { return Reader(builder.asReader()); } inline Reader asReader() const { return Reader(builder.asReader()); } inline uint size() const { return unbound(builder.size() / ELEMENTS); } inline typename T::Client operator[](uint index) { KJ_IREQUIRE(index < size()); return typename T::Client(builder.getPointerElement( bounded(index) * ELEMENTS).getCapability()); } inline void set(uint index, typename T::Client value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook)); } inline void adopt(uint index, Orphan&& value) { KJ_IREQUIRE(index < size()); builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value)); } inline Orphan disown(uint index) { KJ_IREQUIRE(index < size()); return Orphan(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); } typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } private: _::ListBuilder builder; friend class Orphanage; template friend struct ToDynamic_; }; private: inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); } inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { return builder.getList(ElementSize::POINTER, defaultValue); } inline static _::ListReader getFromPointer( const _::PointerReader& reader, const word* defaultValue) { return reader.getList(ElementSize::POINTER, defaultValue); } template friend struct List; template friend struct _::PointerHelpers; }; // ======================================================================================= // Inline implementation details template RemotePromise RemotePromise::reducePromise(kj::Promise&& promise) { kj::Tuple>, kj::Promise>> splitPromise = promise.then([](RemotePromise&& inner) { // `inner` is multiply-inherited, and we want to move away each superclass separately. // Let's create two references to make clear what we're doing (though this is not strictly // necessary). kj::Promise>& innerPromise = inner; typename T::Pipeline& innerPipeline = inner; return kj::tuple(kj::mv(innerPromise), PipelineHook::from(kj::mv(innerPipeline))); }).split(); return RemotePromise(kj::mv(kj::get<0>(splitPromise)), typename T::Pipeline(AnyPointer::Pipeline( newLocalPromisePipeline(kj::mv(kj::get<1>(splitPromise)))))); } template RemotePromise Request::send() { auto typelessPromise = hook->send(); hook = nullptr; // prevent reuse // Convert the Promise to return the correct response type. // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the // Pipeline part of the RemotePromise. auto typedPromise = kj::implicitCast>&>(typelessPromise) .then([](Response&& response) -> Response { return Response(response.getAs(), kj::mv(response.hook)); }); // Wrap the typeless pipeline in a typed wrapper. typename Results::Pipeline typedPipeline( kj::mv(kj::implicitCast(typelessPromise))); return RemotePromise(kj::mv(typedPromise), kj::mv(typedPipeline)); } template typename Results::Pipeline Request::sendForPipeline() { auto typelessPipeline = hook->sendForPipeline(); hook = nullptr; // prevent reuse return typename Results::Pipeline(kj::mv(typelessPipeline)); } template kj::Promise StreamingRequest::send() { auto promise = hook->sendStreaming(); hook = nullptr; // prevent reuse return promise; } inline Capability::Client::Client(kj::Own&& hook): hook(kj::mv(hook)) {} template inline Capability::Client::Client(kj::Own&& server) : hook(makeLocalClient(kj::mv(server))) {} template inline Capability::Client::Client(kj::Promise&& promise) : hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {} inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {} inline Capability::Client& Capability::Client::operator=(Client& other) { hook = other.hook->addRef(); return *this; } template inline typename T::Client Capability::Client::castAs() { return typename T::Client(hook->addRef()); } inline Request Capability::Client::typelessRequest( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) { return newCall(interfaceId, methodId, sizeHint, hints); } template inline Request Capability::Client::newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) { auto typeless = hook->newCall(interfaceId, methodId, sizeHint, hints); return Request(typeless.template getAs(), kj::mv(typeless.hook)); } template inline StreamingRequest Capability::Client::newStreamingCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) { auto typeless = hook->newCall(interfaceId, methodId, sizeHint, hints); return StreamingRequest(typeless.template getAs(), kj::mv(typeless.hook)); } template inline CallContext::CallContext(CallContextHook& hook): hook(&hook) {} template inline StreamingCallContext::StreamingCallContext(CallContextHook& hook): hook(&hook) {} template inline typename Params::Reader CallContext::getParams() { return hook->getParams().template getAs(); } template inline typename Params::Reader StreamingCallContext::getParams() { return hook->getParams().template getAs(); } template inline void CallContext::releaseParams() { hook->releaseParams(); } template inline void StreamingCallContext::releaseParams() { hook->releaseParams(); } template inline typename Results::Builder CallContext::getResults( kj::Maybe sizeHint) { // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401 return hook->getResults(sizeHint).template getAs(); } template inline typename Results::Builder CallContext::initResults( kj::Maybe sizeHint) { // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401 return hook->getResults(sizeHint).template initAs(); } template inline void CallContext::setResults(typename Results::Reader value) { hook->getResults(value.totalSize()).template setAs(value); } template inline void CallContext::adoptResults(Orphan&& value) { hook->getResults(nullptr).adopt(kj::mv(value)); } template inline Orphanage CallContext::getResultsOrphanage( kj::Maybe sizeHint) { return Orphanage::getForMessageContaining(hook->getResults(sizeHint)); } template void CallContext::setPipeline(typename Results::Pipeline&& pipeline) { hook->setPipeline(PipelineHook::from(kj::mv(pipeline))); } template void CallContext::setPipeline(typename Results::Pipeline& pipeline) { hook->setPipeline(PipelineHook::from(pipeline).addRef()); } template template inline kj::Promise CallContext::tailCall( Request&& tailRequest) { return hook->tailCall(kj::mv(tailRequest.hook)); } template CallContext Capability::Server::internalGetTypedContext( CallContext typeless) { return CallContext(*typeless.hook); } template StreamingCallContext Capability::Server::internalGetTypedStreamingContext( CallContext typeless) { return StreamingCallContext(*typeless.hook); } Capability::Client Capability::Server::thisCap() { return Client(thisHook->addRef()); } template RevocableServer::RevocableServer(typename T::Server& server) : hook(Capability::Client::makeRevocableLocalClient(server)) {} template RevocableServer::~RevocableServer() noexcept(false) { // Check if moved away. if (hook.get() != nullptr) { Capability::Client::revokeLocalClient(*hook); } } template typename T::Client RevocableServer::getClient() { return typename T::Client(hook->addRef()); } template void RevocableServer::revoke() { Capability::Client::revokeLocalClient(*hook); } template void RevocableServer::revoke(kj::Exception&& exception) { Capability::Client::revokeLocalClient(*hook, kj::mv(exception)); } namespace _ { // private struct PipelineBuilderPair { AnyPointer::Builder root; kj::Own hook; }; PipelineBuilderPair newPipelineBuilder(uint firstSegmentWords); } // namespace _ (private) template PipelineBuilder::PipelineBuilder(uint firstSegmentWords) : PipelineBuilder(_::newPipelineBuilder(firstSegmentWords)) {} template PipelineBuilder::PipelineBuilder(_::PipelineBuilderPair pair) : T::Builder(pair.root.initAs()), hook(kj::mv(pair.hook)) {} template typename T::Pipeline PipelineBuilder::build() { // Prevent subsequent accidental modification. A good compiler should be able to optimize this // assignment away assuming the PipelineBuilder is not accessed again after this point. static_cast(*this) = nullptr; return typename T::Pipeline(AnyPointer::Pipeline(kj::mv(hook))); } template T ReaderCapabilityTable::imbue(T reader) { return T(_::PointerHelpers>::getInternalReader(reader).imbue(this)); } template T BuilderCapabilityTable::imbue(T builder) { return T(_::PointerHelpers>::getInternalBuilder(kj::mv(builder)).imbue(this)); } template typename T::Client CapabilityServerSet::add(kj::Own&& server) { void* ptr = reinterpret_cast(server.get()); // Clang insists that `castAs` is a template-dependent member and therefore we need the // `template` keyword here, but AFAICT this is wrong: addImpl() is not a template. return addInternal(kj::mv(server), ptr).template castAs(); } template kj::Promise> CapabilityServerSet::getLocalServer( typename T::Client& client) { return getLocalServerInternal(client) .then([](void* server) -> kj::Maybe { if (server == nullptr) { return nullptr; } else { return *reinterpret_cast(server); } }); } template struct Orphanage::GetInnerReader { static inline kj::Own apply(typename T::Client t) { return ClientHook::from(kj::mv(t)); } }; #define CAPNP_CAPABILITY_H_INCLUDED // for testing includes in unit test } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/serialize-packed-test.c++0000644000175000017500000004435214712011043023316 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "serialize-packed.h" #include #include #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { class TestPipe: public kj::BufferedInputStream, public kj::OutputStream { public: TestPipe() : preferredReadSize(kj::maxValue), readPos(0) {} explicit TestPipe(size_t preferredReadSize) : preferredReadSize(preferredReadSize), readPos(0) {} ~TestPipe() {} const std::string& getData() { return data; } kj::ArrayPtr getArray() { return kj::arrayPtr(reinterpret_cast(data.data()), data.size()); } void resetRead(size_t preferredReadSize = kj::maxValue) { readPos = 0; this->preferredReadSize = preferredReadSize; } bool allRead() { return readPos == data.size(); } void clear(size_t preferredReadSize = kj::maxValue) { resetRead(preferredReadSize); data.clear(); } void write(const void* buffer, size_t size) override { data.append(reinterpret_cast(buffer), size); } size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override { KJ_ASSERT(maxBytes <= data.size() - readPos, "Overran end of stream."); size_t amount = kj::min(maxBytes, kj::max(minBytes, preferredReadSize)); memcpy(buffer, data.data() + readPos, amount); readPos += amount; return amount; } void skip(size_t bytes) override { KJ_ASSERT(bytes <= data.size() - readPos, "Overran end of stream."); readPos += bytes; } kj::ArrayPtr tryGetReadBuffer() override { size_t amount = kj::min(data.size() - readPos, preferredReadSize); return kj::arrayPtr(reinterpret_cast(data.data() + readPos), amount); } private: size_t preferredReadSize; std::string data; std::string::size_type readPos; }; void expectPacksTo(kj::ArrayPtr unpackedUnaligned, kj::ArrayPtr packed) { TestPipe pipe; auto unpackedSizeInWords = computeUnpackedSizeInWords(packed); EXPECT_EQ(unpackedUnaligned.size(), unpackedSizeInWords * sizeof(word)); // Make a guaranteed-to-be-aligned copy of the unpacked buffer. kj::Array unpackedWords = kj::heapArray(unpackedSizeInWords); if (unpackedUnaligned.size() != 0u) { memcpy(unpackedWords.begin(), unpackedUnaligned.begin(), unpackedUnaligned.size()); } kj::ArrayPtr unpacked = unpackedWords.asBytes(); // ----------------------------------------------------------------- // write { kj::BufferedOutputStreamWrapper bufferedOut(pipe); PackedOutputStream packedOut(bufferedOut); packedOut.write(unpacked.begin(), unpacked.size()); } if (pipe.getData() != std::string(packed.asChars().begin(), packed.asChars().size())) { KJ_FAIL_ASSERT("Tried to pack `unpacked`, expected `packed`, got `pipe.getData()`", unpacked, packed, pipe.getData()); return; } // ----------------------------------------------------------------- // read kj::Array roundTrip = kj::heapArray(unpacked.size()); { PackedInputStream packedIn(pipe); packedIn.InputStream::read(roundTrip.begin(), roundTrip.size()); EXPECT_TRUE(pipe.allRead()); } if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) { KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`", packed, unpacked, roundTrip); return; } for (uint blockSize = 1; blockSize < packed.size(); blockSize <<= 1) { pipe.resetRead(blockSize); { PackedInputStream packedIn(pipe); packedIn.InputStream::read(roundTrip.begin(), roundTrip.size()); EXPECT_TRUE(pipe.allRead()); } if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) { KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`", packed, blockSize, unpacked, roundTrip); } } // ----------------------------------------------------------------- // skip pipe.resetRead(); { PackedInputStream packedIn(pipe); packedIn.skip(unpacked.size()); EXPECT_TRUE(pipe.allRead()); } for (uint blockSize = 1; blockSize < packed.size(); blockSize <<= 1) { pipe.resetRead(blockSize); { PackedInputStream packedIn(pipe); packedIn.skip(unpacked.size()); EXPECT_TRUE(pipe.allRead()); } } pipe.clear(); // ----------------------------------------------------------------- // write / read multiple { kj::BufferedOutputStreamWrapper bufferedOut(pipe); PackedOutputStream packedOut(bufferedOut); for (uint i = 0; i < 5; i++) { packedOut.write(unpacked.begin(), unpacked.size()); } } for (uint i = 0; i < 5; i++) { PackedInputStream packedIn(pipe); packedIn.InputStream::read(&*roundTrip.begin(), roundTrip.size()); if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) { KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`", packed, i, unpacked, roundTrip); } } EXPECT_TRUE(pipe.allRead()); } #ifdef __CDT_PARSER__ // CDT doesn't seem to understand these initializer lists. #define expectPacksTo(...) #endif TEST(Packed, SimplePacking) { expectPacksTo({}, {}); expectPacksTo({0,0,0,0,0,0,0,0}, {0,0}); expectPacksTo({0,0,12,0,0,34,0,0}, {0x24,12,34}); expectPacksTo({1,3,2,4,5,7,6,8}, {0xff,1,3,2,4,5,7,6,8,0}); expectPacksTo({0,0,0,0,0,0,0,0,1,3,2,4,5,7,6,8}, {0,0,0xff,1,3,2,4,5,7,6,8,0}); expectPacksTo({0,0,12,0,0,34,0,0,1,3,2,4,5,7,6,8}, {0x24,12,34,0xff,1,3,2,4,5,7,6,8,0}); expectPacksTo({1,3,2,4,5,7,6,8,8,6,7,4,5,2,3,1}, {0xff,1,3,2,4,5,7,6,8,1,8,6,7,4,5,2,3,1}); expectPacksTo( {1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1}, {0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0xd6,2,4,9,5,1}); expectPacksTo( {1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1}, {0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0xd6,2,4,9,5,1}); expectPacksTo( {8,0,100,6,0,1,1,2, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,0,2,0,3,1}, {0xed,8,100,6,1,1,2, 0,2, 0xd4,1,2,3,1}); } // ======================================================================================= class TestMessageBuilder: public MallocMessageBuilder { // A MessageBuilder that tries to allocate an exact number of total segments, by allocating // minimum-size segments until it reaches the number, then allocating one large segment to // finish. public: explicit TestMessageBuilder(uint desiredSegmentCount) : MallocMessageBuilder(0, AllocationStrategy::FIXED_SIZE), desiredSegmentCount(desiredSegmentCount) {} ~TestMessageBuilder() { EXPECT_EQ(0u, desiredSegmentCount); } kj::ArrayPtr allocateSegment(uint minimumSize) override { if (desiredSegmentCount <= 1) { if (desiredSegmentCount < 1) { ADD_FAILURE() << "Allocated more segments than desired."; } else { --desiredSegmentCount; } return MallocMessageBuilder::allocateSegment(SUGGESTED_FIRST_SEGMENT_WORDS); } else { --desiredSegmentCount; return MallocMessageBuilder::allocateSegment(minimumSize); } } private: uint desiredSegmentCount; }; TEST(Packed, RoundTrip) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripScratchSpace) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); word scratch[1024]; PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr(scratch, 1024)); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripLazy) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripOddSegmentCount) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripOddSegmentCountLazy) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripEvenSegmentCount) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripEvenSegmentCountLazy) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } TEST(Packed, RoundTripTwoMessages) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); TestMessageBuilder builder2(1); builder2.initRoot().setTextField("Second message."); TestPipe pipe; writePackedMessage(pipe, builder); writePackedMessage(pipe, builder2); EXPECT_EQ(computeSerializedSizeInWords(builder) + computeSerializedSizeInWords(builder2), computeUnpackedSizeInWords(pipe.getArray())); { PackedMessageReader reader(pipe); checkTestMessage(reader.getRoot()); } { PackedMessageReader reader(pipe); EXPECT_EQ("Second message.", reader.getRoot().getTextField()); } } // ======================================================================================= TEST(Packed, RoundTripAllZero) { TestMessageBuilder builder(1); builder.initRoot(); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); // Segment table packs to 2 bytes. // Root pointer packs to 3 bytes. // Content packs to 2 bytes (zero span). EXPECT_LE(pipe.getData().size(), 7u); } TEST(Packed, RoundTripAllZeroScratchSpace) { TestMessageBuilder builder(1); builder.initRoot(); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); word scratch[1024]; PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr(scratch, 1024)); checkTestMessageAllZero(reader.getRoot()); } TEST(Packed, RoundTripAllZeroLazy) { TestMessageBuilder builder(1); builder.initRoot(); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); } TEST(Packed, RoundTripAllZeroOddSegmentCount) { TestMessageBuilder builder(3); builder.initRoot().initStructField().initStructField(); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); } TEST(Packed, RoundTripAllZeroOddSegmentCountLazy) { TestMessageBuilder builder(3); builder.initRoot().initStructField().initStructField(); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); } TEST(Packed, RoundTripAllZeroEvenSegmentCount) { TestMessageBuilder builder(2); builder.initRoot().initStructField().initStructField(); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); } TEST(Packed, RoundTripAllZeroEvenSegmentCountLazy) { TestMessageBuilder builder(2); builder.initRoot().initStructField().initStructField(); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); checkTestMessageAllZero(reader.getRoot()); } // ======================================================================================= TEST(Packed, RoundTripHugeString) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(1); builder.initRoot().setTextField(huge); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringScratchSpace) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(1); builder.initRoot().setTextField(huge); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); word scratch[1024]; PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr(scratch, 1024)); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringLazy) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(1); builder.initRoot().setTextField(huge); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringOddSegmentCount) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(3); builder.initRoot().setTextField(huge); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringOddSegmentCountLazy) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(3); builder.initRoot().setTextField(huge); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringEvenSegmentCount) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(2); builder.initRoot().setTextField(huge); TestPipe pipe; writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } TEST(Packed, RoundTripHugeStringEvenSegmentCountLazy) { kj::String huge = kj::heapString(5023); memset(huge.begin(), 'x', 5023); TestMessageBuilder builder(2); builder.initRoot().setTextField(huge); TestPipe pipe(1); writePackedMessage(pipe, builder); EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray())); PackedMessageReader reader(pipe); EXPECT_TRUE(reader.getRoot().getTextField() == huge); } // TODO(test): Test error cases. } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/dynamic.h0000644000175000017500000017136214712011043020432 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file defines classes that can be used to manipulate messages based on schemas that are not // known until runtime. This is also useful for writing generic code that uses schemas to handle // arbitrary types in a generic way. // // Each of the classes defined here has a to() template method which converts an instance back to a // native type. This method will throw an exception if the requested type does not match the // schema. To convert native types to dynamic, use DynamicFactory. // // As always, underlying data is validated lazily, so you have to actually traverse the whole // message if you want to validate all content. #pragma once #include "schema.h" #include "layout.h" #include "message.h" #include "any.h" #include "capability.h" #include // work-around macro conflict with `VOID` CAPNP_BEGIN_HEADER namespace capnp { class MessageReader; class MessageBuilder; struct DynamicValue { DynamicValue() = delete; enum Type { UNKNOWN, // Means that the value has unknown type and content because it comes from a newer version of // the schema, or from a newer version of Cap'n Proto that has new features that this version // doesn't understand. VOID, BOOL, INT, UINT, FLOAT, TEXT, DATA, LIST, ENUM, STRUCT, CAPABILITY, ANY_POINTER }; class Reader; class Builder; class Pipeline; }; class DynamicEnum; struct DynamicStruct { DynamicStruct() = delete; class Reader; class Builder; class Pipeline; }; struct DynamicList { DynamicList() = delete; class Reader; class Builder; }; struct DynamicCapability { DynamicCapability() = delete; class Client; class Server; }; template <> class Orphan; template struct DynamicTypeFor_; template <> struct DynamicTypeFor_ { typedef DynamicEnum Type; }; template <> struct DynamicTypeFor_ { typedef DynamicStruct Type; }; template <> struct DynamicTypeFor_ { typedef DynamicList Type; }; template <> struct DynamicTypeFor_ { typedef DynamicCapability Type; }; template using DynamicTypeFor = typename DynamicTypeFor_()>::Type; template ReaderFor>> toDynamic(T&& value); template BuilderFor>> toDynamic(T&& value); template DynamicTypeFor> toDynamic(T&& value); template typename DynamicTypeFor>::Client toDynamic(kj::Own&& value); namespace _ { // private template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; } // namespace _ (private) template <> inline constexpr Style style() { return Style::POINTER; } template <> inline constexpr Style style() { return Style::PRIMITIVE; } template <> inline constexpr Style style() { return Style::STRUCT; } template <> inline constexpr Style style() { return Style::POINTER; } template <> inline constexpr Style style() { return Style::CAPABILITY; } // ------------------------------------------------------------------- class DynamicEnum { public: DynamicEnum() = default; inline DynamicEnum(EnumSchema::Enumerant enumerant) : schema(enumerant.getContainingEnum()), value(enumerant.getOrdinal()) {} inline DynamicEnum(EnumSchema schema, uint16_t value) : schema(schema), value(value) {} template () == Kind::ENUM>> inline DynamicEnum(T&& value): DynamicEnum(toDynamic(value)) {} template inline T as() const { return static_cast(asImpl(typeId())); } // Cast to a native enum type. inline EnumSchema getSchema() const { return schema; } kj::Maybe getEnumerant() const; // Get which enumerant this enum value represents. Returns nullptr if the numeric value does not // correspond to any enumerant in the schema -- this can happen if the data was built using a // newer schema that has more values defined. inline uint16_t getRaw() const { return value; } // Returns the raw underlying enum value. private: EnumSchema schema; uint16_t value; uint16_t asImpl(uint64_t requestedTypeId) const; friend struct DynamicStruct; friend struct DynamicList; friend struct DynamicValue; template friend DynamicTypeFor> toDynamic(T&& value); }; // ------------------------------------------------------------------- enum class HasMode: uint8_t { // Specifies the meaning of "has(field)". NON_NULL, // "has(field)" only returns false if the field is a pointer and the pointer is null. This is the // default behavior. NON_DEFAULT // "has(field)" returns false if the field is set to its default value. This differs from // NON_NULL only in the handling of primitive values. // // "Equal to default value" is technically defined as the field value being encoded as all-zero // on the wire (since primitive values are XORed by their defined default value when encoded). }; class DynamicStruct::Reader { public: typedef DynamicStruct Reads; Reader() = default; template >() == Kind::STRUCT>> inline Reader(T&& value): Reader(toDynamic(value)) {} inline operator AnyStruct::Reader() const { return AnyStruct::Reader(reader); } inline MessageSize totalSize() const { return reader.totalSize().asPublic(); } template typename T::Reader as() const; // Convert the dynamic struct to its compiled-in type. inline StructSchema getSchema() const { return schema; } DynamicValue::Reader get(StructSchema::Field field) const; // Read the given field value. bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL) const; // Tests whether the given field is "present". If the field is a union member and is not the // active member, this always returns false. Otherwise, the field's value is interpreted // according to `mode`. kj::Maybe which() const; // If the struct contains an (unnamed) union, and the currently-active field within that union // is known, this returns that field. Otherwise, it returns null. In other words, this returns // null if there is no union present _or_ if the union's discriminant is set to an unrecognized // value. This could happen in particular when receiving a message from a sender who has a // newer version of the protocol and is using a field of the union that you don't know about yet. DynamicValue::Reader get(kj::StringPtr name) const; bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL) const; // Shortcuts to access fields by name. These throw exceptions if no such field exists. private: StructSchema schema; _::StructReader reader; inline Reader(StructSchema schema, _::StructReader reader) : schema(schema), reader(reader) {} Reader(StructSchema schema, const _::OrphanBuilder& orphan); bool isSetInUnion(StructSchema::Field field) const; void verifySetInUnion(StructSchema::Field field) const; static DynamicValue::Reader getImpl(_::StructReader reader, StructSchema::Field field); template friend struct _::PointerHelpers; friend class DynamicStruct::Builder; friend struct DynamicList; friend class MessageReader; friend class MessageBuilder; template friend struct ::capnp::ToDynamic_; friend kj::StringTree _::structString( _::StructReader reader, const _::RawBrandedSchema& schema); friend class Orphanage; friend class Orphan; friend class Orphan; friend class Orphan; friend class AnyStruct::Reader; }; class DynamicStruct::Builder { public: typedef DynamicStruct Builds; Builder() = default; inline Builder(decltype(nullptr)) {} template >() == Kind::STRUCT>> inline Builder(T&& value): Builder(toDynamic(value)) {} inline operator AnyStruct::Builder() { return AnyStruct::Builder(builder); } inline MessageSize totalSize() const { return asReader().totalSize(); } template typename T::Builder as(); // Cast to a particular struct type. inline StructSchema getSchema() const { return schema; } DynamicValue::Builder get(StructSchema::Field field); // Read the given field value. inline bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL) { return asReader().has(field, mode); } // Tests whether the given field is "present". If the field is a union member and is not the // active member, this always returns false. Otherwise, the field's value is interpreted // according to `mode`. kj::Maybe which(); // If the struct contains an (unnamed) union, and the currently-active field within that union // is known, this returns that field. Otherwise, it returns null. In other words, this returns // null if there is no union present _or_ if the union's discriminant is set to an unrecognized // value. This could happen in particular when receiving a message from a sender who has a // newer version of the protocol and is using a field of the union that you don't know about yet. void set(StructSchema::Field field, const DynamicValue::Reader& value); // Set the given field value. DynamicValue::Builder init(StructSchema::Field field); DynamicValue::Builder init(StructSchema::Field field, uint size); // Init a struct, list, or blob field. void adopt(StructSchema::Field field, Orphan&& orphan); Orphan disown(StructSchema::Field field); // Adopt/disown. This works even for non-pointer fields: adopt() becomes equivalent to set() // and disown() becomes like get() followed by clear(). void clear(StructSchema::Field field); // Clear a field, setting it to its default value. For pointer fields, this actually makes the // field null. DynamicValue::Builder get(kj::StringPtr name); bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL); void set(kj::StringPtr name, const DynamicValue::Reader& value); void set(kj::StringPtr name, std::initializer_list value); DynamicValue::Builder init(kj::StringPtr name); DynamicValue::Builder init(kj::StringPtr name, uint size); void adopt(kj::StringPtr name, Orphan&& orphan); Orphan disown(kj::StringPtr name); void clear(kj::StringPtr name); // Shortcuts to access fields by name. These throw exceptions if no such field exists. Reader asReader() const; private: StructSchema schema; _::StructBuilder builder; inline Builder(StructSchema schema, _::StructBuilder builder) : schema(schema), builder(builder) {} Builder(StructSchema schema, _::OrphanBuilder& orphan); bool isSetInUnion(StructSchema::Field field); void verifySetInUnion(StructSchema::Field field); void setInUnion(StructSchema::Field field); template friend struct _::PointerHelpers; friend struct DynamicList; friend class MessageReader; friend class MessageBuilder; template friend struct ::capnp::ToDynamic_; friend class Orphanage; friend class Orphan; friend class Orphan; friend class Orphan; friend class AnyStruct::Builder; }; class DynamicStruct::Pipeline { public: typedef DynamicStruct Pipelines; inline Pipeline(decltype(nullptr)): typeless(nullptr) {} template typename T::Pipeline releaseAs(); // Convert the dynamic pipeline to its compiled-in type. inline StructSchema getSchema() { return schema; } DynamicValue::Pipeline get(StructSchema::Field field); // Read the given field value. DynamicValue::Pipeline get(kj::StringPtr name); // Get by string name. private: StructSchema schema; AnyPointer::Pipeline typeless; inline explicit Pipeline(StructSchema schema, AnyPointer::Pipeline&& typeless) : schema(schema), typeless(kj::mv(typeless)) {} friend class Request; }; // ------------------------------------------------------------------- class DynamicList::Reader { public: typedef DynamicList Reads; inline Reader(): reader(ElementSize::VOID) {} template >() == Kind::LIST>> inline Reader(T&& value): Reader(toDynamic(value)) {} inline operator AnyList::Reader() const { return AnyList::Reader(reader); } template typename T::Reader as() const; // Try to convert to any List, Data, or Text. Throws an exception if the underlying data // can't possibly represent the requested type. inline ListSchema getSchema() const { return schema; } inline uint size() const { return unbound(reader.size() / ELEMENTS); } DynamicValue::Reader operator[](uint index) const; typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: ListSchema schema; _::ListReader reader; Reader(ListSchema schema, _::ListReader reader): schema(schema), reader(reader) {} Reader(ListSchema schema, const _::OrphanBuilder& orphan); template friend struct _::PointerHelpers; friend struct DynamicStruct; friend class DynamicList::Builder; template friend struct ::capnp::ToDynamic_; friend class Orphanage; friend class Orphan; friend class Orphan; friend class Orphan; }; class DynamicList::Builder { public: typedef DynamicList Builds; inline Builder(): builder(ElementSize::VOID) {} inline Builder(decltype(nullptr)): builder(ElementSize::VOID) {} template >() == Kind::LIST>> inline Builder(T&& value): Builder(toDynamic(value)) {} inline operator AnyList::Builder() { return AnyList::Builder(builder); } template typename T::Builder as(); // Try to convert to any List, Data, or Text. Throws an exception if the underlying data // can't possibly represent the requested type. inline ListSchema getSchema() const { return schema; } inline uint size() const { return unbound(builder.size() / ELEMENTS); } DynamicValue::Builder operator[](uint index); void set(uint index, const DynamicValue::Reader& value); DynamicValue::Builder init(uint index, uint size); void adopt(uint index, Orphan&& orphan); Orphan disown(uint index); typedef _::IndexingIterator Iterator; inline Iterator begin() { return Iterator(this, 0); } inline Iterator end() { return Iterator(this, size()); } void copyFrom(std::initializer_list value); Reader asReader() const; private: ListSchema schema; _::ListBuilder builder; Builder(ListSchema schema, _::ListBuilder builder): schema(schema), builder(builder) {} Builder(ListSchema schema, _::OrphanBuilder& orphan); template friend struct _::PointerHelpers; friend struct DynamicStruct; template friend struct ::capnp::ToDynamic_; friend class Orphanage; template friend struct _::OrphanGetImpl; friend class Orphan; friend class Orphan; friend class Orphan; }; // ------------------------------------------------------------------- class DynamicCapability::Client: public Capability::Client { public: typedef DynamicCapability Calls; typedef DynamicCapability Reads; Client() = default; template >() == Kind::INTERFACE>> inline Client(T&& client); template ()>> inline Client(kj::Own&& server); template () == Kind::INTERFACE>> typename T::Client as(); template () == Kind::INTERFACE>> typename T::Client releaseAs(); // Convert to any client type. Client upcast(InterfaceSchema requestedSchema); // Upcast to a superclass. Throws an exception if `schema` is not a superclass. inline InterfaceSchema getSchema() { return schema; } Request newRequest( InterfaceSchema::Method method, kj::Maybe sizeHint = nullptr); Request newRequest( kj::StringPtr methodName, kj::Maybe sizeHint = nullptr); private: InterfaceSchema schema; Client(InterfaceSchema schema, kj::Own&& hook) : Capability::Client(kj::mv(hook)), schema(schema) {} template inline Client(InterfaceSchema schema, kj::Own&& server); friend struct Capability; friend struct DynamicStruct; friend struct DynamicList; friend struct DynamicValue; friend class Orphan; friend class Orphan; friend class Orphan; template friend struct _::PointerHelpers; }; class DynamicCapability::Server: public Capability::Server { public: typedef DynamicCapability Serves; struct Options { bool allowCancellation = false; // See the `allowCancellation` annotation defined in `c++.capnp`. // // This option applies to all calls made to this server object. The annotation in the schema // is NOT used for dynamic servers. }; Server(InterfaceSchema schema): schema(schema) {} Server(InterfaceSchema schema, Options options): schema(schema), options(options) {} virtual kj::Promise call(InterfaceSchema::Method method, CallContext context) = 0; DispatchCallResult dispatchCall(uint64_t interfaceId, uint16_t methodId, CallContext context) override final; inline InterfaceSchema getSchema() const { return schema; } private: InterfaceSchema schema; Options options; }; template <> class Request: public DynamicStruct::Builder { // Specialization of `Request` for DynamicStruct. public: inline Request(DynamicStruct::Builder builder, kj::Own&& hook, StructSchema resultSchema) : DynamicStruct::Builder(builder), hook(kj::mv(hook)), resultSchema(resultSchema) {} RemotePromise send(); // Send the call and return a promise for the results. kj::Promise sendStreaming(); // Use when the caller is aware that the response type is StreamResult and wants to invoke // streaming behavior. It is an error to call this if the response type is not StreamResult. private: kj::Own hook; StructSchema resultSchema; friend class Capability::Client; friend struct DynamicCapability; template friend class CallContext; friend class RequestHook; }; template <> class CallContext: public kj::DisallowConstCopy { // Wrapper around CallContextHook with a specific return type. // // Methods of this class may only be called from within the server's event loop, not from other // threads. public: explicit CallContext(CallContextHook& hook, StructSchema paramType, StructSchema resultType); DynamicStruct::Reader getParams(); void releaseParams(); DynamicStruct::Builder getResults(kj::Maybe sizeHint = nullptr); DynamicStruct::Builder initResults(kj::Maybe sizeHint = nullptr); void setResults(DynamicStruct::Reader value); void adoptResults(Orphan&& value); Orphanage getResultsOrphanage(kj::Maybe sizeHint = nullptr); template kj::Promise tailCall(Request&& tailRequest); StructSchema getParamsType() const { return paramType; } StructSchema getResultsType() const { return resultType; } private: CallContextHook* hook; StructSchema paramType; StructSchema resultType; friend class DynamicCapability::Server; }; // ------------------------------------------------------------------- // Make sure ReaderFor and BuilderFor work for DynamicEnum, DynamicStruct, and // DynamicList, so that we can define DynamicValue::as(). template <> struct ReaderFor_ { typedef DynamicEnum Type; }; template <> struct BuilderFor_ { typedef DynamicEnum Type; }; template <> struct ReaderFor_ { typedef DynamicStruct::Reader Type; }; template <> struct BuilderFor_ { typedef DynamicStruct::Builder Type; }; template <> struct ReaderFor_ { typedef DynamicList::Reader Type; }; template <> struct BuilderFor_ { typedef DynamicList::Builder Type; }; template <> struct ReaderFor_ { typedef DynamicCapability::Client Type; }; template <> struct BuilderFor_ { typedef DynamicCapability::Client Type; }; template <> struct PipelineFor_ { typedef DynamicCapability::Client Type; }; class DynamicValue::Reader { public: typedef DynamicValue Reads; inline Reader(decltype(nullptr) n = nullptr); // UNKNOWN inline Reader(Void value); inline Reader(bool value); inline Reader(char value); inline Reader(signed char value); inline Reader(short value); inline Reader(int value); inline Reader(long value); inline Reader(long long value); inline Reader(unsigned char value); inline Reader(unsigned short value); inline Reader(unsigned int value); inline Reader(unsigned long value); inline Reader(unsigned long long value); inline Reader(float value); inline Reader(double value); inline Reader(const char* value); // Text inline Reader(const Text::Reader& value); inline Reader(const Data::Reader& value); inline Reader(const DynamicList::Reader& value); inline Reader(DynamicEnum value); inline Reader(const DynamicStruct::Reader& value); inline Reader(const AnyPointer::Reader& value); inline Reader(DynamicCapability::Client& value); inline Reader(DynamicCapability::Client&& value); template ()>> inline Reader(kj::Own&& value); Reader(ConstSchema constant); template ()))> inline Reader(T&& value): Reader(toDynamic(kj::mv(value))) {} Reader(const Reader& other); Reader(Reader&& other) noexcept; ~Reader() noexcept(false); Reader& operator=(const Reader& other); Reader& operator=(Reader&& other); // Unfortunately, we cannot use the implicit definitions of these since DynamicCapability is not // trivially copyable. template inline ReaderFor as() const { return AsImpl::apply(*this); } // Use to interpret the value as some Cap'n Proto type. Allowed types are: // - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum: Returns the raw value. // - Text, Data, AnyPointer, any struct type: Returns the corresponding Reader. // - List for any T listed above: Returns List::Reader. // - DynamicEnum: Returns the corresponding type. // - DynamicStruct, DynamicList: Returns the corresponding Reader. // - Any capability type, including DynamicCapability: Returns the corresponding Client. // - DynamicValue: Returns an identical Reader. Useful to avoid special-casing in generic code. // (TODO(perf): On GCC 4.8 / Clang 3.3, provide rvalue-qualified version that avoids // refcounting.) // // DynamicValue allows various implicit conversions, mostly just to make the interface friendlier. // - Any integer can be converted to any other integer type so long as the actual value is within // the new type's range. // - Floating-point types can be converted to integers as long as no information would be lost // in the conversion. // - Integers can be converted to floating points. This may lose information, but won't throw. // - Float32/Float64 can be converted between each other. Converting Float64 -> Float32 may lose // information, but won't throw. // - Text can be converted to an enum, if the Text matches one of the enumerant names (but not // vice-versa). // - Capabilities can be upcast (cast to a supertype), but not downcast. // // Any other conversion attempt will throw an exception. inline Type getType() const { return type; } // Get the type of this value. private: Type type; union { Void voidValue; bool boolValue; int64_t intValue; uint64_t uintValue; double floatValue; Text::Reader textValue; Data::Reader dataValue; DynamicList::Reader listValue; DynamicEnum enumValue; DynamicStruct::Reader structValue; AnyPointer::Reader anyPointerValue; mutable DynamicCapability::Client capabilityValue; // Declared mutable because `Client`s normally cannot be const. // Warning: Copy/move constructors assume all these types are trivially copyable except // Capability. }; template ()> struct AsImpl; // Implementation backing the as() method. Needs to be a struct to allow partial // specialization. Has a method apply() which does the work. friend class Orphanage; // to speed up newOrphanCopy(DynamicValue::Reader) }; class DynamicValue::Builder { public: typedef DynamicValue Builds; inline Builder(decltype(nullptr) n = nullptr); // UNKNOWN inline Builder(Void value); inline Builder(bool value); inline Builder(char value); inline Builder(signed char value); inline Builder(short value); inline Builder(int value); inline Builder(long value); inline Builder(long long value); inline Builder(unsigned char value); inline Builder(unsigned short value); inline Builder(unsigned int value); inline Builder(unsigned long value); inline Builder(unsigned long long value); inline Builder(float value); inline Builder(double value); inline Builder(Text::Builder value); inline Builder(Data::Builder value); inline Builder(DynamicList::Builder value); inline Builder(DynamicEnum value); inline Builder(DynamicStruct::Builder value); inline Builder(AnyPointer::Builder value); inline Builder(DynamicCapability::Client& value); inline Builder(DynamicCapability::Client&& value); template ()))> inline Builder(T value): Builder(toDynamic(value)) {} Builder(Builder& other); Builder(Builder&& other) noexcept; ~Builder() noexcept(false); Builder& operator=(Builder& other); Builder& operator=(Builder&& other); // Unfortunately, we cannot use the implicit definitions of these since DynamicCapability is not // trivially copyable. template inline BuilderFor as() { return AsImpl::apply(*this); } // See DynamicValue::Reader::as(). inline Type getType() { return type; } // Get the type of this value. Reader asReader() const; private: Type type; union { Void voidValue; bool boolValue; int64_t intValue; uint64_t uintValue; double floatValue; Text::Builder textValue; Data::Builder dataValue; DynamicList::Builder listValue; DynamicEnum enumValue; DynamicStruct::Builder structValue; AnyPointer::Builder anyPointerValue; mutable DynamicCapability::Client capabilityValue; // Declared mutable because `Client`s normally cannot be const. }; template ()> struct AsImpl; // Implementation backing the as() method. Needs to be a struct to allow partial // specialization. Has a method apply() which does the work. friend class Orphan; }; class DynamicValue::Pipeline { public: typedef DynamicValue Pipelines; inline Pipeline(decltype(nullptr) n = nullptr); inline Pipeline(DynamicStruct::Pipeline&& value); inline Pipeline(DynamicCapability::Client&& value); Pipeline(Pipeline&& other) noexcept; Pipeline& operator=(Pipeline&& other); ~Pipeline() noexcept(false); template inline PipelineFor releaseAs() { return AsImpl::apply(*this); } inline Type getType() { return type; } // Get the type of this value. private: Type type; union { DynamicStruct::Pipeline structValue; DynamicCapability::Client capabilityValue; }; template ()> struct AsImpl; // Implementation backing the releaseAs() method. Needs to be a struct to allow partial // specialization. Has a method apply() which does the work. }; kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value); kj::StringTree KJ_STRINGIFY(DynamicEnum value); kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value); kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value); kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value); // ------------------------------------------------------------------- // Orphan <-> Dynamic glue template <> class Orphan { public: Orphan() = default; KJ_DISALLOW_COPY(Orphan); Orphan(Orphan&&) = default; Orphan& operator=(Orphan&&) = default; template () == Kind::STRUCT>> inline Orphan(Orphan&& other): schema(Schema::from()), builder(kj::mv(other.builder)) {} DynamicStruct::Builder get(); DynamicStruct::Reader getReader() const; template Orphan releaseAs(); // Like DynamicStruct::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, // the original Orphan is no longer valid after this call; ownership is // transferred to the returned Orphan. inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } private: StructSchema schema; _::OrphanBuilder builder; inline Orphan(StructSchema schema, _::OrphanBuilder&& builder) : schema(schema), builder(kj::mv(builder)) {} template friend struct _::PointerHelpers; friend struct DynamicList; friend class Orphanage; friend class Orphan; friend class Orphan; friend class MessageBuilder; }; template <> class Orphan { public: Orphan() = default; KJ_DISALLOW_COPY(Orphan); Orphan(Orphan&&) = default; Orphan& operator=(Orphan&&) = default; template () == Kind::LIST>> inline Orphan(Orphan&& other): schema(Schema::from()), builder(kj::mv(other.builder)) {} DynamicList::Builder get(); DynamicList::Reader getReader() const; template Orphan releaseAs(); // Like DynamicList::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, // the original Orphan is no longer valid after this call; ownership is // transferred to the returned Orphan. // TODO(someday): Support truncate(). inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } private: ListSchema schema; _::OrphanBuilder builder; inline Orphan(ListSchema schema, _::OrphanBuilder&& builder) : schema(schema), builder(kj::mv(builder)) {} template friend struct _::PointerHelpers; friend struct DynamicList; friend class Orphanage; friend class Orphan; friend class Orphan; }; template <> class Orphan { public: Orphan() = default; KJ_DISALLOW_COPY(Orphan); Orphan(Orphan&&) = default; Orphan& operator=(Orphan&&) = default; template () == Kind::INTERFACE>> inline Orphan(Orphan&& other): schema(Schema::from()), builder(kj::mv(other.builder)) {} DynamicCapability::Client get(); DynamicCapability::Client getReader() const; template Orphan releaseAs(); // Like DynamicCapability::Client::as(), but coerces the Orphan type. Since Orphans are move-only, // the original Orphan is no longer valid after this call; ownership is // transferred to the returned Orphan. inline bool operator==(decltype(nullptr)) const { return builder == nullptr; } inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; } private: InterfaceSchema schema; _::OrphanBuilder builder; inline Orphan(InterfaceSchema schema, _::OrphanBuilder&& builder) : schema(schema), builder(kj::mv(builder)) {} template friend struct _::PointerHelpers; friend struct DynamicList; friend class Orphanage; friend class Orphan; friend class Orphan; }; template <> class Orphan { public: inline Orphan(decltype(nullptr) n = nullptr): type(DynamicValue::UNKNOWN) {} inline Orphan(Void value); inline Orphan(bool value); inline Orphan(char value); inline Orphan(signed char value); inline Orphan(short value); inline Orphan(int value); inline Orphan(long value); inline Orphan(long long value); inline Orphan(unsigned char value); inline Orphan(unsigned short value); inline Orphan(unsigned int value); inline Orphan(unsigned long value); inline Orphan(unsigned long long value); inline Orphan(float value); inline Orphan(double value); inline Orphan(DynamicEnum value); Orphan(Orphan&&) = default; template Orphan(Orphan&&); Orphan(Orphan&&); Orphan(void*) = delete; // So Orphan(bool) doesn't accept pointers. KJ_DISALLOW_COPY(Orphan); Orphan& operator=(Orphan&&) = default; inline DynamicValue::Type getType() { return type; } DynamicValue::Builder get(); DynamicValue::Reader getReader() const; template Orphan releaseAs(); // Like DynamicValue::Builder::as(), but coerces the Orphan type. Since Orphans are move-only, // the original Orphan is no longer valid after this call; ownership is // transferred to the returned Orphan. private: DynamicValue::Type type; union { Void voidValue; bool boolValue; int64_t intValue; uint64_t uintValue; double floatValue; DynamicEnum enumValue; StructSchema structSchema; ListSchema listSchema; InterfaceSchema interfaceSchema; }; _::OrphanBuilder builder; // Only used if `type` is a pointer type. Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder); Orphan(DynamicValue::Type type, _::OrphanBuilder&& builder) : type(type), builder(kj::mv(builder)) {} Orphan(StructSchema structSchema, _::OrphanBuilder&& builder) : type(DynamicValue::STRUCT), structSchema(structSchema), builder(kj::mv(builder)) {} Orphan(ListSchema listSchema, _::OrphanBuilder&& builder) : type(DynamicValue::LIST), listSchema(listSchema), builder(kj::mv(builder)) {} template friend struct _::PointerHelpers; friend struct DynamicStruct; friend struct DynamicList; friend struct AnyPointer; friend class Orphanage; }; template inline Orphan::Orphan(Orphan&& other) : Orphan(other.get(), kj::mv(other.builder)) {} inline Orphan::Orphan(Orphan&& other) : type(DynamicValue::ANY_POINTER), builder(kj::mv(other.builder)) {} template Orphan Orphan::releaseAs() { get().as(); // type check return Orphan(kj::mv(builder)); } template Orphan Orphan::releaseAs() { get().as(); // type check return Orphan(kj::mv(builder)); } template Orphan Orphan::releaseAs() { get().as(); // type check return Orphan(kj::mv(builder)); } template Orphan Orphan::releaseAs() { get().as(); // type check type = DynamicValue::UNKNOWN; return Orphan(kj::mv(builder)); } template <> Orphan Orphan::releaseAs(); template <> Orphan Orphan::releaseAs(); template <> Orphan Orphan::releaseAs(); template <> Orphan Orphan::releaseAs(); template <> struct Orphanage::GetInnerBuilder { static inline _::StructBuilder apply(DynamicStruct::Builder& t) { return t.builder; } }; template <> struct Orphanage::GetInnerBuilder { static inline _::ListBuilder apply(DynamicList::Builder& t) { return t.builder; } }; template <> inline Orphan Orphanage::newOrphanCopy( DynamicStruct::Reader copyFrom) const { return Orphan( copyFrom.getSchema(), _::OrphanBuilder::copy(arena, capTable, copyFrom.reader)); } template <> inline Orphan Orphanage::newOrphanCopy( DynamicList::Reader copyFrom) const { return Orphan(copyFrom.getSchema(), _::OrphanBuilder::copy(arena, capTable, copyFrom.reader)); } template <> inline Orphan Orphanage::newOrphanCopy( DynamicCapability::Client copyFrom) const { return Orphan( copyFrom.getSchema(), _::OrphanBuilder::copy(arena, capTable, copyFrom.hook->addRef())); } template <> Orphan Orphanage::newOrphanCopy( DynamicValue::Reader copyFrom) const; namespace _ { // private template <> struct PointerHelpers { // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we // don't want people to accidentally be able to provide their own default value. static DynamicStruct::Reader getDynamic(PointerReader reader, StructSchema schema); static DynamicStruct::Builder getDynamic(PointerBuilder builder, StructSchema schema); static void set(PointerBuilder builder, const DynamicStruct::Reader& value); static DynamicStruct::Builder init(PointerBuilder builder, StructSchema schema); static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder, StructSchema schema) { return Orphan(schema, builder.disown()); } }; template <> struct PointerHelpers { // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we // don't want people to accidentally be able to provide their own default value. static DynamicList::Reader getDynamic(PointerReader reader, ListSchema schema); static DynamicList::Builder getDynamic(PointerBuilder builder, ListSchema schema); static void set(PointerBuilder builder, const DynamicList::Reader& value); static DynamicList::Builder init(PointerBuilder builder, ListSchema schema, uint size); static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder, ListSchema schema) { return Orphan(schema, builder.disown()); } }; template <> struct PointerHelpers { // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we // don't want people to accidentally be able to provide their own default value. static DynamicCapability::Client getDynamic(PointerReader reader, InterfaceSchema schema); static DynamicCapability::Client getDynamic(PointerBuilder builder, InterfaceSchema schema); static void set(PointerBuilder builder, DynamicCapability::Client& value); static void set(PointerBuilder builder, DynamicCapability::Client&& value); static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder, InterfaceSchema schema) { return Orphan(schema, builder.disown()); } }; } // namespace _ (private) template inline ReaderFor AnyPointer::Reader::getAs(StructSchema schema) const { return _::PointerHelpers::getDynamic(reader, schema); } template inline ReaderFor AnyPointer::Reader::getAs(ListSchema schema) const { return _::PointerHelpers::getDynamic(reader, schema); } template inline ReaderFor AnyPointer::Reader::getAs(InterfaceSchema schema) const { return _::PointerHelpers::getDynamic(reader, schema); } template inline BuilderFor AnyPointer::Builder::getAs(StructSchema schema) { return _::PointerHelpers::getDynamic(builder, schema); } template inline BuilderFor AnyPointer::Builder::getAs(ListSchema schema) { return _::PointerHelpers::getDynamic(builder, schema); } template inline BuilderFor AnyPointer::Builder::getAs(InterfaceSchema schema) { return _::PointerHelpers::getDynamic(builder, schema); } template inline BuilderFor AnyPointer::Builder::initAs(StructSchema schema) { return _::PointerHelpers::init(builder, schema); } template inline BuilderFor AnyPointer::Builder::initAs(ListSchema schema, uint elementCount) { return _::PointerHelpers::init(builder, schema, elementCount); } template <> inline void AnyPointer::Builder::setAs(DynamicStruct::Reader value) { return _::PointerHelpers::set(builder, value); } template <> inline void AnyPointer::Builder::setAs(DynamicList::Reader value) { return _::PointerHelpers::set(builder, value); } template <> inline void AnyPointer::Builder::setAs(DynamicCapability::Client value) { return _::PointerHelpers::set(builder, kj::mv(value)); } template <> void AnyPointer::Builder::adopt(Orphan&& orphan); template inline Orphan AnyPointer::Builder::disownAs(StructSchema schema) { return _::PointerHelpers::disown(builder, schema); } template inline Orphan AnyPointer::Builder::disownAs(ListSchema schema) { return _::PointerHelpers::disown(builder, schema); } template inline Orphan AnyPointer::Builder::disownAs(InterfaceSchema schema) { return _::PointerHelpers::disown(builder, schema); } // We have to declare the methods below inline because Clang and GCC disagree about how to mangle // their symbol names. template <> inline DynamicStruct::Builder Orphan::getAs(StructSchema schema) { return DynamicStruct::Builder(schema, builder); } template <> inline DynamicStruct::Reader Orphan::getAsReader( StructSchema schema) const { return DynamicStruct::Reader(schema, builder); } template <> inline Orphan Orphan::releaseAs(StructSchema schema) { return Orphan(schema, kj::mv(builder)); } template <> inline DynamicList::Builder Orphan::getAs(ListSchema schema) { return DynamicList::Builder(schema, builder); } template <> inline DynamicList::Reader Orphan::getAsReader(ListSchema schema) const { return DynamicList::Reader(schema, builder); } template <> inline Orphan Orphan::releaseAs(ListSchema schema) { return Orphan(schema, kj::mv(builder)); } template <> inline DynamicCapability::Client Orphan::getAs( InterfaceSchema schema) { return DynamicCapability::Client(schema, builder.asCapability()); } template <> inline DynamicCapability::Client Orphan::getAsReader( InterfaceSchema schema) const { return DynamicCapability::Client(schema, builder.asCapability()); } template <> inline Orphan Orphan::releaseAs( InterfaceSchema schema) { return Orphan(schema, kj::mv(builder)); } // ======================================================================================= // Inline implementation details. template struct ToDynamic_ { static inline DynamicStruct::Reader apply(const typename T::Reader& value) { return DynamicStruct::Reader(Schema::from(), value._reader); } static inline DynamicStruct::Builder apply(typename T::Builder& value) { return DynamicStruct::Builder(Schema::from(), value._builder); } }; template struct ToDynamic_ { static inline DynamicList::Reader apply(const typename T::Reader& value) { return DynamicList::Reader(Schema::from(), value.reader); } static inline DynamicList::Builder apply(typename T::Builder& value) { return DynamicList::Builder(Schema::from(), value.builder); } }; template struct ToDynamic_ { static inline DynamicCapability::Client apply(typename T::Client value) { return DynamicCapability::Client(kj::mv(value)); } static inline DynamicCapability::Client apply(typename T::Client&& value) { return DynamicCapability::Client(kj::mv(value)); } }; template ReaderFor>> toDynamic(T&& value) { return ToDynamic_>::apply(value); } template BuilderFor>> toDynamic(T&& value) { return ToDynamic_>::apply(value); } template DynamicTypeFor> toDynamic(T&& value) { return DynamicEnum(Schema::from>(), static_cast(value)); } template typename DynamicTypeFor>::Client toDynamic(kj::Own&& value) { return typename FromServer::Client(kj::mv(value)); } inline DynamicValue::Reader::Reader(std::nullptr_t n): type(UNKNOWN) {} inline DynamicValue::Builder::Builder(std::nullptr_t n): type(UNKNOWN) {} #define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \ inline DynamicValue::Reader::Reader(cppType value) \ : type(typeTag), fieldName##Value(value) {} \ inline DynamicValue::Builder::Builder(cppType value) \ : type(typeTag), fieldName##Value(value) {} \ inline Orphan::Orphan(cppType value) \ : type(DynamicValue::typeTag), fieldName##Value(value) {} CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Void, VOID, void); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(bool, BOOL, bool); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(char, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(signed char, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(short, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(int, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long long, INT, int); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned char, UINT, uint); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned short, UINT, uint); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned int, UINT, uint); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long, UINT, uint); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long long, UINT, uint); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(float, FLOAT, float); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(double, FLOAT, float); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicEnum, ENUM, enum); #undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR #define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \ inline DynamicValue::Reader::Reader(const cppType::Reader& value) \ : type(typeTag), fieldName##Value(value) {} \ inline DynamicValue::Builder::Builder(cppType::Builder value) \ : type(typeTag), fieldName##Value(value) {} CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct); CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(AnyPointer, ANY_POINTER, anyPointer); #undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR inline DynamicValue::Reader::Reader(DynamicCapability::Client& value) : type(CAPABILITY), capabilityValue(value) {} inline DynamicValue::Reader::Reader(DynamicCapability::Client&& value) : type(CAPABILITY), capabilityValue(kj::mv(value)) {} template inline DynamicValue::Reader::Reader(kj::Own&& value) : type(CAPABILITY), capabilityValue(kj::mv(value)) {} inline DynamicValue::Builder::Builder(DynamicCapability::Client& value) : type(CAPABILITY), capabilityValue(value) {} inline DynamicValue::Builder::Builder(DynamicCapability::Client&& value) : type(CAPABILITY), capabilityValue(kj::mv(value)) {} inline DynamicValue::Reader::Reader(const char* value): Reader(Text::Reader(value)) {} #define CAPNP_DECLARE_TYPE(discrim, typeName) \ template <> \ struct DynamicValue::Reader::AsImpl { \ static ReaderFor apply(const Reader& reader); \ }; \ template <> \ struct DynamicValue::Builder::AsImpl { \ static BuilderFor apply(Builder& builder); \ }; //CAPNP_DECLARE_TYPE(VOID, Void) CAPNP_DECLARE_TYPE(BOOL, bool) CAPNP_DECLARE_TYPE(INT8, int8_t) CAPNP_DECLARE_TYPE(INT16, int16_t) CAPNP_DECLARE_TYPE(INT32, int32_t) CAPNP_DECLARE_TYPE(INT64, int64_t) CAPNP_DECLARE_TYPE(UINT8, uint8_t) CAPNP_DECLARE_TYPE(UINT16, uint16_t) CAPNP_DECLARE_TYPE(UINT32, uint32_t) CAPNP_DECLARE_TYPE(UINT64, uint64_t) CAPNP_DECLARE_TYPE(FLOAT32, float) CAPNP_DECLARE_TYPE(FLOAT64, double) CAPNP_DECLARE_TYPE(TEXT, Text) CAPNP_DECLARE_TYPE(DATA, Data) CAPNP_DECLARE_TYPE(LIST, DynamicList) CAPNP_DECLARE_TYPE(STRUCT, DynamicStruct) CAPNP_DECLARE_TYPE(INTERFACE, DynamicCapability) CAPNP_DECLARE_TYPE(ENUM, DynamicEnum) CAPNP_DECLARE_TYPE(ANY_POINTER, AnyPointer) #undef CAPNP_DECLARE_TYPE // CAPNP_DECLARE_TYPE(Void) causes gcc 4.7 to segfault. If I do it manually and remove the // ReaderFor<> and BuilderFor<> wrappers, it works. template <> struct DynamicValue::Reader::AsImpl { static Void apply(const Reader& reader); }; template <> struct DynamicValue::Builder::AsImpl { static Void apply(Builder& builder); }; template struct DynamicValue::Reader::AsImpl { static T apply(const Reader& reader) { return reader.as().as(); } }; template struct DynamicValue::Builder::AsImpl { static T apply(Builder& builder) { return builder.as().as(); } }; template struct DynamicValue::Reader::AsImpl { static typename T::Reader apply(const Reader& reader) { return reader.as().as(); } }; template struct DynamicValue::Builder::AsImpl { static typename T::Builder apply(Builder& builder) { return builder.as().as(); } }; template struct DynamicValue::Reader::AsImpl { static typename T::Reader apply(const Reader& reader) { return reader.as().as(); } }; template struct DynamicValue::Builder::AsImpl { static typename T::Builder apply(Builder& builder) { return builder.as().as(); } }; template struct DynamicValue::Reader::AsImpl { static typename T::Client apply(const Reader& reader) { return reader.as().as(); } }; template struct DynamicValue::Builder::AsImpl { static typename T::Client apply(Builder& builder) { return builder.as().as(); } }; template <> struct DynamicValue::Reader::AsImpl { static DynamicValue::Reader apply(const Reader& reader) { return reader; } }; template <> struct DynamicValue::Builder::AsImpl { static DynamicValue::Builder apply(Builder& builder) { return builder; } }; inline DynamicValue::Pipeline::Pipeline(std::nullptr_t n): type(UNKNOWN) {} inline DynamicValue::Pipeline::Pipeline(DynamicStruct::Pipeline&& value) : type(STRUCT), structValue(kj::mv(value)) {} inline DynamicValue::Pipeline::Pipeline(DynamicCapability::Client&& value) : type(CAPABILITY), capabilityValue(kj::mv(value)) {} template struct DynamicValue::Pipeline::AsImpl { static typename T::Pipeline apply(Pipeline& pipeline) { return pipeline.releaseAs().releaseAs(); } }; template struct DynamicValue::Pipeline::AsImpl { static typename T::Client apply(Pipeline& pipeline) { return pipeline.releaseAs().releaseAs(); } }; template <> struct DynamicValue::Pipeline::AsImpl { static PipelineFor apply(Pipeline& pipeline); }; template <> struct DynamicValue::Pipeline::AsImpl { static PipelineFor apply(Pipeline& pipeline); }; // ------------------------------------------------------------------- template typename T::Reader DynamicStruct::Reader::as() const { static_assert(kind() == Kind::STRUCT, "DynamicStruct::Reader::as() can only convert to struct types."); schema.requireUsableAs(); return typename T::Reader(reader); } template typename T::Builder DynamicStruct::Builder::as() { static_assert(kind() == Kind::STRUCT, "DynamicStruct::Builder::as() can only convert to struct types."); schema.requireUsableAs(); return typename T::Builder(builder); } template <> inline DynamicStruct::Reader DynamicStruct::Reader::as() const { return *this; } template <> inline DynamicStruct::Builder DynamicStruct::Builder::as() { return *this; } inline DynamicStruct::Reader DynamicStruct::Builder::asReader() const { return DynamicStruct::Reader(schema, builder.asReader()); } template <> inline AnyStruct::Reader DynamicStruct::Reader::as() const { return AnyStruct::Reader(reader); } template <> inline AnyStruct::Builder DynamicStruct::Builder::as() { return AnyStruct::Builder(builder); } template <> inline DynamicStruct::Reader AnyStruct::Reader::as(StructSchema schema) const { return DynamicStruct::Reader(schema, _reader); } template <> inline DynamicStruct::Builder AnyStruct::Builder::as(StructSchema schema) { return DynamicStruct::Builder(schema, _builder); } template typename T::Pipeline DynamicStruct::Pipeline::releaseAs() { static_assert(kind() == Kind::STRUCT, "DynamicStruct::Pipeline::releaseAs() can only convert to struct types."); schema.requireUsableAs(); return typename T::Pipeline(kj::mv(typeless)); } // ------------------------------------------------------------------- template typename T::Reader DynamicList::Reader::as() const { static_assert(kind() == Kind::LIST, "DynamicStruct::Reader::as() can only convert to list types."); schema.requireUsableAs(); return typename T::Reader(reader); } template typename T::Builder DynamicList::Builder::as() { static_assert(kind() == Kind::LIST, "DynamicStruct::Builder::as() can only convert to list types."); schema.requireUsableAs(); return typename T::Builder(builder); } template <> inline DynamicList::Reader DynamicList::Reader::as() const { return *this; } template <> inline DynamicList::Builder DynamicList::Builder::as() { return *this; } template <> inline AnyList::Reader DynamicList::Reader::as() const { return AnyList::Reader(reader); } template <> inline AnyList::Builder DynamicList::Builder::as() { return AnyList::Builder(builder); } // ------------------------------------------------------------------- template inline DynamicCapability::Client::Client(T&& client) : Capability::Client(kj::mv(client)), schema(Schema::from>()) {} template inline DynamicCapability::Client::Client(kj::Own&& server) : Client(server->getSchema(), kj::mv(server)) {} template inline DynamicCapability::Client::Client(InterfaceSchema schema, kj::Own&& server) : Capability::Client(kj::mv(server)), schema(schema) {} template typename T::Client DynamicCapability::Client::as() { static_assert(kind() == Kind::INTERFACE, "DynamicCapability::Client::as() can only convert to interface types."); schema.requireUsableAs(); return typename T::Client(hook->addRef()); } template typename T::Client DynamicCapability::Client::releaseAs() { static_assert(kind() == Kind::INTERFACE, "DynamicCapability::Client::as() can only convert to interface types."); schema.requireUsableAs(); return typename T::Client(kj::mv(hook)); } inline CallContext::CallContext( CallContextHook& hook, StructSchema paramType, StructSchema resultType) : hook(&hook), paramType(paramType), resultType(resultType) {} inline DynamicStruct::Reader CallContext::getParams() { return hook->getParams().getAs(paramType); } inline void CallContext::releaseParams() { hook->releaseParams(); } inline DynamicStruct::Builder CallContext::getResults( kj::Maybe sizeHint) { return hook->getResults(sizeHint).getAs(resultType); } inline DynamicStruct::Builder CallContext::initResults( kj::Maybe sizeHint) { return hook->getResults(sizeHint).initAs(resultType); } inline void CallContext::setResults(DynamicStruct::Reader value) { hook->getResults(value.totalSize()).setAs(value); } inline void CallContext::adoptResults(Orphan&& value) { hook->getResults(MessageSize { 0, 0 }).adopt(kj::mv(value)); } inline Orphanage CallContext::getResultsOrphanage( kj::Maybe sizeHint) { return Orphanage::getForMessageContaining(hook->getResults(sizeHint)); } template inline kj::Promise CallContext::tailCall( Request&& tailRequest) { return hook->tailCall(kj::mv(tailRequest.hook)); } template <> inline DynamicCapability::Client Capability::Client::castAs( InterfaceSchema schema) { return DynamicCapability::Client(schema, hook->addRef()); } template <> inline DynamicCapability::Client CapabilityServerSet::add( kj::Own&& server) { void* ptr = reinterpret_cast(server.get()); auto schema = server->getSchema(); return addInternal(kj::mv(server), ptr).castAs(schema); } // ------------------------------------------------------------------- template ReaderFor ConstSchema::as() const { return DynamicValue::Reader(*this).as(); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/membrane.h0000644000175000017500000003773314712011043020577 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once // In capability theory, a "membrane" is a wrapper around a capability which (usually) forwards // calls but recursively wraps capabilities in those calls in the same membrane. The purpose of a // membrane is to enforce a barrier between two capabilities that cannot be bypassed by merely // introducing new objects. // // The most common use case for a membrane is revocation: Say Alice wants to give Bob a capability // to access Carol, but wants to be able to revoke this capability later. Alice can accomplish this // by wrapping Carol in a revokable wrapper which passes through calls until such a time as Alice // indicates it should be revoked, after which all calls through the wrapper will throw exceptions. // However, a naive wrapper approach has a problem: if Bob makes a call to Carol and sends a new // capability in that call, or if Carol returns a capability to Bob in the response to a call, then // the two are now able to communicate using this new capability, which Alice cannot revoke. In // order to avoid this problem, Alice must use not just a wrapper but a "membrane", which // recursively wraps all objects that pass through it in either direction. Thus, all connections // formed between Bob and Carol (originating from Alice's original introduction) can be revoked // together by revoking the membrane. // // Note that when a capability is passed into a membrane and then passed back out, the result is // the original capability, not a double-membraned capability. This means that in our revocation // example, if Bob uses his capability to Carol to obtain another capability from her, then send // it back to her, the capability Carol receives back will NOT be revoked when Bob's access to // Carol is revoked. Thus Bob can create long-term irrevocable connections. In most practical use // cases, this is what you want. APIs commonly rely on the fact that a capability obtained and then // passed back can be recognized as the original capability. // // Mark Miller on membranes: http://www.eros-os.org/pipermail/e-lang/2003-January/008434.html #include "capability.h" #include CAPNP_BEGIN_HEADER namespace capnp { class MembranePolicy { // Applications may implement this interface to define a membrane policy, which allows some // calls crossing the membrane to be blocked or redirected. public: virtual kj::Maybe inboundCall( uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0; // Given an inbound call (a call originating "outside" the membrane destined for an object // "inside" the membrane), decides what to do with it. The policy may: // // - Return null to indicate that the call should proceed to the destination. All capabilities // in the parameters or result will be properly wrapped in the same membrane. // - Return a capability to have the call redirected to that capability. Note that the redirect // capability will be treated as outside the membrane, so the params and results will not be // auto-wrapped; however, the callee can easily wrap the returned capability in the membrane // itself before returning to achieve this effect. // - Throw an exception to cause the call to fail with that exception. // // `target` is the underlying capability (*inside* the membrane) for which the call is destined. // Generally, the only way you should use `target` is to wrap it in some capability which you // return as a redirect. The redirect capability may modify the call in some way and send it to // `target`. Be careful to use `copyIntoMembrane()` and `copyOutOfMembrane()` as appropriate when // copying parameters or results across the membrane. // // Note that since `target` is inside the capability, if you were to directly return it (rather // than return null), the effect would be that the membrane would be broken: the call would // proceed directly and any new capabilities introduced through it would not be membraned. You // generally should not do that. virtual kj::Maybe outboundCall( uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0; // Like `inboundCall()`, but applies to calls originating *inside* the membrane and terminating // outside. // // Note: It is strongly recommended that `outboundCall()` returns null in exactly the same cases // that `inboundCall()` return null. Conversely, for any case where `inboundCall()` would // redirect or throw, `outboundCall()` should also redirect or throw. Otherwise, you can run // into inconsistent behavion when a promise is returned across a membrane, and that promise // later resolves to a capability on the other side of the membrane: calls on the promise // will enter and then exit the membrane, but calls on the eventual resolution will not cross // the membrane at all, so it is important that these two cases behave the same. virtual kj::Own addRef() = 0; // Return a new owned pointer to the same policy. // // Typically an implementation of MembranePolicy should also inherit kj::Refcounted and implement // `addRef()` as `return kj::addRef(*this);`. // // Note that the membraning system considers two membranes created with the same MembranePolicy // object actually to be the *same* membrane. This is relevant when an object passes into the // membrane and then back out (or out and then back in): instead of double-wrapping the object, // the wrapping will be removed. virtual kj::Maybe> onRevoked() { return nullptr; } // If this returns non-null, then it is a promise that will reject (throw an exception) when the // membrane should be revoked. On revocation, all capabilities pointing across the membrane will // be dropped and all outstanding calls canceled. The exception thrown by the promise will be // propagated to all these calls. It is an error for the promise to resolve without throwing. // // After the revocation promise has rejected, inboundCall() and outboundCall() will still be // invoked for new calls, but the `target` passed to them will be a capability that always // rethrows the revocation exception. virtual bool shouldResolveBeforeRedirecting() { return false; } // If this returns true, then when inboundCall() or outboundCall() returns a redirect, but the // original target is a promise, then the membrane will discard the redirect and instead wait // for the promise to become more resolved and try again. // // This behavior is important in particular when implementing a membrane that wants to intercept // calls that would otherwise terminate inside the membrane, but needs to be careful not to // intercept calls that might be reflected back out of the membrane. If the promise eventually // resolves to a capability outside the membrane, then the call will be forwarded to that // capability without applying the policy at all. // // However, some membranes don't need this behavior, and may be negatively impacted by the // unnecessary waiting. Such membranes can keep this disabled. // // TODO(cleanup): Consider a backwards-incompatible revamp of the MembranePolicy API with a // better design here. Maybe we should more carefully distinguish between MembranePolicies // which are reversible vs. those which are one-way? virtual bool allowFdPassthrough() { return false; } // Should file descriptors be allowed to pass through this membrane? // // A MembranePolicy obviously cannot mediate nor revoke access to a file descriptor once it has // passed through, so this must be used with caution. If you only want to allow file descriptors // on certain methods, you could do so by implementing inboundCall()/outboundCall() to // special-case those methods. // --------------------------------------------------------------------------- // Control over importing and exporting. // // Most membranes should not override these methods. The default behavior is that a capability // that crosses the membrane is wrapped in it, and if the wrapped version crosses back the other // way, it is unwrapped. virtual Capability::Client importExternal(Capability::Client external); // An external capability is crossing into the membrane. Returns the capability that should // substitute for it when called from the inside. // // The default implementation creates a capability that invokes this MembranePolicy. E.g. all // calls will invoke outboundCall(). // // Note that reverseMembrane(cap, policy) normally calls policy->importExternal(cap), unless // `cap` itself was originally returned by the default implementation of exportInternal(), in // which case importInternal() is called instead. virtual Capability::Client exportInternal(Capability::Client internal); // An internal capability is crossing out of the membrane. Returns the capability that should // substitute for it when called from the outside. // // The default implementation creates a capability that invokes this MembranePolicy. E.g. all // calls will invoke inboundCall(). // // Note that membrane(cap, policy) normally calls policy->exportInternal(cap), unless `cap` // itself was originally returned by the default implementation of exportInternal(), in which // case importInternal() is called instead. virtual MembranePolicy& rootPolicy() { return *this; } // If two policies return the same value for rootPolicy(), then a capability imported through // one can be exported through the other, and vice versa. `importInternal()` and // `exportExternal()` will always be called on the root policy, passing the two child policies // as parameters. If you don't override rootPolicy(), then the policy references passed to // importInternal() and exportExternal() will always be references to *this. virtual Capability::Client importInternal( Capability::Client internal, MembranePolicy& exportPolicy, MembranePolicy& importPolicy); // An internal capability which was previously exported is now being re-imported, i.e. a // capability passed out of the membrane and then back in. // // The default implementation simply returns `internal`. virtual Capability::Client exportExternal( Capability::Client external, MembranePolicy& importPolicy, MembranePolicy& exportPolicy); // An external capability which was previously imported is now being re-exported, i.e. a // capability passed into the membrane and then back out. // // The default implementation simply returns `external`. private: kj::HashMap wrappers; kj::HashMap reverseWrappers; // Tracks capabilities that already have wrappers instantiated. The maps map from pointer to // inner capability to pointer to wrapper. When a wrapper is destroyed it removes itself from // the map. friend class MembraneHook; }; Capability::Client membrane(Capability::Client inner, kj::Own policy); // Wrap `inner` in a membrane specified by `policy`. `inner` is considered "inside" the membrane, // while the returned capability should only be called from outside the membrane. Capability::Client reverseMembrane(Capability::Client outer, kj::Own policy); // Like `membrane` but treat the input capability as "outside" the membrane, and return a // capability appropriate for use inside. // // Applications typically won't use this directly; the membraning code automatically sets up // reverse membranes where needed. template ClientType membrane(ClientType inner, kj::Own policy); template ClientType reverseMembrane(ClientType inner, kj::Own policy); // Convenience templates which return the same interface type as the input. template typename ServerType::Serves::Client membrane( kj::Own inner, kj::Own policy); template typename ServerType::Serves::Client reverseMembrane( kj::Own inner, kj::Own policy); // Convenience templates which input a capability server type and return the appropriate client // type. template Orphan::Reads> copyIntoMembrane( Reader&& from, Orphanage to, kj::Own policy); // Copy a Cap'n Proto object (e.g. struct or list), adding the given membrane to any capabilities // found within it. `from` is interpreted as "outside" the membrane while `to` is "inside". template Orphan::Reads> copyOutOfMembrane( Reader&& from, Orphanage to, kj::Own policy); // Like copyIntoMembrane() except that `from` is "inside" the membrane and `to` is "outside". // ======================================================================================= // inline implementation details template ClientType membrane(ClientType inner, kj::Own policy) { return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) .castAs(); } template ClientType reverseMembrane(ClientType inner, kj::Own policy) { return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) .castAs(); } template typename ServerType::Serves::Client membrane( kj::Own inner, kj::Own policy) { return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) .castAs(); } template typename ServerType::Serves::Client reverseMembrane( kj::Own inner, kj::Own policy) { return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy)) .castAs(); } namespace _ { // private OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to, kj::Own policy, bool reverse); OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to, kj::Own policy, bool reverse); OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to, kj::Own policy, bool reverse); } // namespace _ (private) template Orphan::Reads> copyIntoMembrane( Reader&& from, Orphanage to, kj::Own policy) { return _::copyOutOfMembrane( _::PointerHelpers::Reads>::getInternalReader(from), to, kj::mv(policy), true); } template Orphan::Reads> copyOutOfMembrane( Reader&& from, Orphanage to, kj::Own policy) { return _::copyOutOfMembrane( _::PointerHelpers::Reads>::getInternalReader(from), to, kj::mv(policy), false); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/stream.capnp.c++0000644000175000017500000000365114712011043021515 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: stream.capnp #include "stream.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<17> b_995f9a3377c0b16e = { { 0, 0, 0, 0, 5, 0, 6, 0, 110, 177, 192, 119, 51, 154, 95, 153, 19, 0, 0, 0, 1, 0, 0, 0, 248, 243, 147, 19, 169, 102, 195, 134, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 2, 1, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 115, 116, 114, 101, 97, 109, 46, 99, 97, 112, 110, 112, 58, 83, 116, 114, 101, 97, 109, 82, 101, 115, 117, 108, 116, 0, 0, 0, 0, 0, 1, 0, 1, 0, } }; ::capnp::word const* const bp_995f9a3377c0b16e = b_995f9a3377c0b16e.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_995f9a3377c0b16e = { 0x995f9a3377c0b16e, b_995f9a3377c0b16e.words, 17, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_995f9a3377c0b16e, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { // StreamResult #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t StreamResult::_capnpPrivate::dataWordSize; constexpr uint16_t StreamResult::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind StreamResult::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* StreamResult::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace capnproto-c++-1.1.0/src/capnp/ez-rpc.h0000644000175000017500000002675414712011043020212 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "rpc.h" #include "message.h" CAPNP_BEGIN_HEADER struct sockaddr; namespace kj { class AsyncIoProvider; class LowLevelAsyncIoProvider; } namespace capnp { class EzRpcContext; class EzRpcClient { // Super-simple interface for setting up a Cap'n Proto RPC client. Example: // // # Cap'n Proto schema // interface Adder { // add @0 (left :Int32, right :Int32) -> (value :Int32); // } // // // C++ client // int main() { // capnp::EzRpcClient client("localhost:3456"); // Adder::Client adder = client.getMain(); // auto request = adder.addRequest(); // request.setLeft(12); // request.setRight(34); // auto response = request.send().wait(client.getWaitScope()); // assert(response.getValue() == 46); // return 0; // } // // // C++ server // class AdderImpl final: public Adder::Server { // public: // kj::Promise add(AddContext context) override { // auto params = context.getParams(); // context.getResults().setValue(params.getLeft() + params.getRight()); // return kj::READY_NOW; // } // }; // // int main() { // capnp::EzRpcServer server(kj::heap(), "*:3456"); // kj::NEVER_DONE.wait(server.getWaitScope()); // } // // This interface is easy, but it hides a lot of useful features available from the lower-level // classes: // - The server can only export a small set of public, singleton capabilities under well-known // string names. This is fine for transient services where no state needs to be kept between // connections, but hides the power of Cap'n Proto when it comes to long-lived resources. // - EzRpcClient/EzRpcServer automatically set up a `kj::EventLoop` and make it current for the // thread. Only one `kj::EventLoop` can exist per thread, so you cannot use these interfaces // if you wish to set up your own event loop. (However, you can safely create multiple // EzRpcClient / EzRpcServer objects in a single thread; they will make sure to make no more // than one EventLoop.) // - These classes only support simple two-party connections, not multilateral VatNetworks. // - These classes only support communication over a raw, unencrypted socket. If you want to // build on an abstract stream (perhaps one which supports encryption), you must use the // lower-level interfaces. // // Some of these restrictions will probably be lifted in future versions, but some things will // always require using the low-level interfaces directly. If you are interested in working // at a lower level, start by looking at these interfaces: // - `kj::setupAsyncIo()` in `kj/async-io.h`. // - `RpcSystem` in `capnp/rpc.h`. // - `TwoPartyVatNetwork` in `capnp/rpc-twoparty.h`. public: explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions()); // Construct a new EzRpcClient and connect to the given address. The connection is formed in // the background -- if it fails, calls to capabilities returned by importCap() will fail with an // appropriate exception. // // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly. // If unspecified, the port is required in `serverAddress`. // // The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info // on the address format, but basically it's what you'd expect. // // `readerOpts` is the ReaderOptions structure used to read each incoming message on the // connection. Setting this may be necessary if you need to receive very large individual // messages or messages. However, it is recommended that you instead think about how to change // your protocol to send large data blobs in multiple small chunks -- this is much better for // both security and performance. See `ReaderOptions` in `message.h` for more details. EzRpcClient(const struct sockaddr* serverAddress, uint addrSize, ReaderOptions readerOpts = ReaderOptions()); // Like the above constructor, but connects to an already-resolved socket address. Any address // format supported by `kj::Network` in `kj/async-io.h` is accepted. explicit EzRpcClient(int socketFd, ReaderOptions readerOpts = ReaderOptions()); // Create a client on top of an already-connected socket. // `readerOpts` acts as in the first constructor. ~EzRpcClient() noexcept(false); template typename Type::Client getMain(); Capability::Client getMain(); // Get the server's main (aka "bootstrap") interface. template typename Type::Client importCap(kj::StringPtr name) CAPNP_DEPRECATED( "Change your server to export a main interface, then use getMain() instead."); Capability::Client importCap(kj::StringPtr name) CAPNP_DEPRECATED( "Change your server to export a main interface, then use getMain() instead."); // ** DEPRECATED ** // // Ask the sever for the capability with the given name. You may specify a type to automatically // down-cast to that type. It is up to you to specify the correct expected type. // // Named interfaces are deprecated. The new preferred usage pattern is for the server to export // a "main" interface which itself has methods for getting any other interfaces. kj::WaitScope& getWaitScope(); // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on // promises. kj::AsyncIoProvider& getIoProvider(); // Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want // to do some non-RPC I/O in asynchronous fashion. kj::LowLevelAsyncIoProvider& getLowLevelIoProvider(); // Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you // want to do some non-RPC I/O in asynchronous fashion. private: struct Impl; kj::Own impl; }; class EzRpcServer { // The server counterpart to `EzRpcClient`. See `EzRpcClient` for an example. public: explicit EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress, uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions()); // Construct a new `EzRpcServer` that binds to the given address. An address of "*" means to // bind to all local addresses. // // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly. // If unspecified, a port is chosen automatically, and you must call getPort() to find out what // it is. // // The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info // on the address format, but basically it's what you'd expect. // // The server might not begin listening immediately, especially if `bindAddress` needs to be // resolved. If you need to wait until the server is definitely up, wait on the promise returned // by `getPort()`. // // `readerOpts` is the ReaderOptions structure used to read each incoming message on the // connection. Setting this may be necessary if you need to receive very large individual // messages or messages. However, it is recommended that you instead think about how to change // your protocol to send large data blobs in multiple small chunks -- this is much better for // both security and performance. See `ReaderOptions` in `message.h` for more details. EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts = ReaderOptions()); // Like the above constructor, but binds to an already-resolved socket address. Any address // format supported by `kj::Network` in `kj/async-io.h` is accepted. EzRpcServer(Capability::Client mainInterface, int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions()); // Create a server on top of an already-listening socket (i.e. one on which accept() may be // called). `port` is returned by `getPort()` -- it serves no other purpose. // `readerOpts` acts as in the other two above constructors. explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions()) CAPNP_DEPRECATED("Please specify a main interface for your server."); EzRpcServer(struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts = ReaderOptions()) CAPNP_DEPRECATED("Please specify a main interface for your server."); EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions()) CAPNP_DEPRECATED("Please specify a main interface for your server."); ~EzRpcServer() noexcept(false); void exportCap(kj::StringPtr name, Capability::Client cap); // Export a capability publicly under the given name, so that clients can import it. // // Keep in mind that you can implicitly convert `kj::Own&&` to // `Capability::Client`, so it's typical to pass something like // `kj::heap()` as the second parameter. kj::Promise getPort(); // Get the IP port number on which this server is listening. This promise won't resolve until // the server is actually listening. If the address was not an IP address (e.g. it was a Unix // domain socket) then getPort() resolves to zero. kj::WaitScope& getWaitScope(); // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on // promises. kj::AsyncIoProvider& getIoProvider(); // Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want // to do some non-RPC I/O in asynchronous fashion. kj::LowLevelAsyncIoProvider& getLowLevelIoProvider(); // Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you // want to do some non-RPC I/O in asynchronous fashion. private: struct Impl; kj::Own impl; }; // ======================================================================================= // inline implementation details template inline typename Type::Client EzRpcClient::getMain() { return getMain().castAs(); } template inline typename Type::Client EzRpcClient::importCap(kj::StringPtr name) { return importCap(name).castAs(); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/testdata/0000755000175000017500000000000014731562205020450 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/capnp/testdata/binary0000644000175000017500000000540014527152321021653 0ustar00kentonkenton00000000000000_…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšD»àÀ‚‹µÉM"ML…0!……… … …$‰%•©Áwfoobarô€ LûNsè8¦3ZÒˆbÒ o!Ì_p ¯u@M"ML%!)!"!#!$%%1"1#1$5%A4I5]q…wÕbazquxM:HnestedMrreally nested Þ€ÒÒé€ÿNa¼@Ó ú€ÿÿÿyß †Hp.uýŠ–ýÿ€ÿÿÿÿÿÿÿ "ÿÒ.ÿÿNa¼À,_ÿÿÿÿyß †HpÒŠìuiÿÿÿÿÿÿÿÿ8´–I½ð|½ðüêê‚@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€ * 2 :quuxcorgegrault 2 * "garplywaldofred z½z]zx structlist 1x structlist 2x structlist 3 o‘g+™ÔÇkŸ9”`ùÇqÄ+«uk9Ž;ÔTŠ”ðoÞ5‚œ­U¡®ÆÇq¬µ¯˜2šœ­E€€ÿÀÀa¾@ððÿø 2 2 *plughxyzzythud " J :oopsexhaustedrfc3092 j½j]jstructlist 1structlist 2structlist 3capnproto-c++-1.1.0/src/capnp/testdata/short.json0000644000175000017500000001030214527152321022473 0ustar00kentonkenton00000000000000{"voidField":null,"boolField":true,"int8Field":-123,"int16Field":-12345,"int32Field":-12345678,"int64Field":"-123456789012345","uInt8Field":234,"uInt16Field":45678,"uInt32Field":3456789012,"uInt64Field":"12345678901234567890","float32Field":1234.5,"float64Field":-1.23e47,"textField":"foo","dataField":[98,97,114],"structField":{"voidField":null,"boolField":true,"int8Field":-12,"int16Field":3456,"int32Field":-78901234,"int64Field":"56789012345678","uInt8Field":90,"uInt16Field":1234,"uInt32Field":56789012,"uInt64Field":"345678901234567890","float32Field":-1.2499999646475857e-10,"float64Field":345,"textField":"baz","dataField":[113,117,120],"structField":{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"nested","structField":{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"really nested","enumField":"foo","interfaceField":null},"enumField":"foo","interfaceField":null},"enumField":"baz","interfaceField":null,"voidList":[null,null,null],"boolList":[false,true,false,true,true],"int8List":[12,-34,-128,127],"int16List":[1234,-5678,-32768,32767],"int32List":[12345678,-90123456,-2147483648,2147483647],"int64List":["123456789012345","-678901234567890","-9223372036854775808","9223372036854775807"],"uInt8List":[12,34,0,255],"uInt16List":[1234,5678,0,65535],"uInt32List":[12345678,90123456,0,4294967295],"uInt64List":["123456789012345","678901234567890","0","18446744073709551615"],"float32List":[0,1234567,9.9999999338158125e36,-9.9999999338158125e36,9.99999991097579e-38,-9.99999991097579e-38],"float64List":[0,123456789012345,1e306,-1e306,1e-306,-1e-306],"textList":["quux","corge","grault"],"dataList":[[103,97,114,112,108,121],[119,97,108,100,111],[102,114,101,100]],"structList":[{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"x structlist 1","enumField":"foo","interfaceField":null},{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"x structlist 2","enumField":"foo","interfaceField":null},{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"x structlist 3","enumField":"foo","interfaceField":null}],"enumList":["qux","bar","grault"]},"enumField":"corge","interfaceField":null,"voidList":[null,null,null,null,null,null],"boolList":[true,false,false,true],"int8List":[111,-111],"int16List":[11111,-11111],"int32List":[111111111,-111111111],"int64List":["1111111111111111111","-1111111111111111111"],"uInt8List":[111,222],"uInt16List":[33333,44444],"uInt32List":[3333333333],"uInt64List":["11111111111111111111"],"float32List":[5555.5,"Infinity","-Infinity","NaN"],"float64List":[7777.75,"Infinity","-Infinity","NaN"],"textList":["plugh","xyzzy","thud"],"dataList":[[111,111,112,115],[101,120,104,97,117,115,116,101,100],[114,102,99,51,48,57,50]],"structList":[{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"structlist 1","enumField":"foo","interfaceField":null},{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"structlist 2","enumField":"foo","interfaceField":null},{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":"0","uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":"0","float32Field":0,"float64Field":0,"textField":"structlist 3","enumField":"foo","interfaceField":null}],"enumList":["foo","garply"]} capnproto-c++-1.1.0/src/capnp/testdata/annotated-json.binary0000644000175000017500000000104014527152321024572 0ustar00kentonkenton00000000000000C{A¦="="="=]"]"\e:e#d±"±*¬fooabccbathis is a long string in order to force multi-line pretty printingfedghi2corgegarplyO À^@ 2hello:objectfredplugh"cbacapnproto-c++-1.1.0/src/capnp/testdata/flat0000644000175000017500000000537014527152321021323 0ustar00kentonkenton00000000000000…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšD»àÀ‚‹µÉM"ML…0!……… … …$‰%•©Áwfoobarô€ LûNsè8¦3ZÒˆbÒ o!Ì_p ¯u@M"ML%!)!"!#!$%%1"1#1$5%A4I5]q…wÕbazquxM:HnestedMrreally nested Þ€ÒÒé€ÿNa¼@Ó ú€ÿÿÿyß †Hp.uýŠ–ýÿ€ÿÿÿÿÿÿÿ "ÿÒ.ÿÿNa¼À,_ÿÿÿÿyß †HpÒŠìuiÿÿÿÿÿÿÿÿ8´–I½ð|½ðüêê‚@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€ * 2 :quuxcorgegrault 2 * "garplywaldofred z½z]zx structlist 1x structlist 2x structlist 3 o‘g+™ÔÇkŸ9”`ùÇqÄ+«uk9Ž;ÔTŠ”ðoÞ5‚œ­U¡®ÆÇq¬µ¯˜2šœ­E€€ÿÀÀa¾@ððÿø 2 2 *plughxyzzythud " J :oopsexhaustedrfc3092 j½j]jstructlist 1structlist 2structlist 3capnproto-c++-1.1.0/src/capnp/testdata/no-file-id.capnp.nobuild0000644000175000017500000000003114527152321025040 0ustar00kentonkenton00000000000000const foo :Text = "bar"; capnproto-c++-1.1.0/src/capnp/testdata/errors2.txt0000644000175000017500000000046414527152321022610 0ustar00kentonkenton00000000000000file:31:18-29: error: Cannot interpret value because the type is a generic type parameter which is not yet bound. We don't know what type to expect here. file:32:30-41: error: Cannot interpret value because the type is a generic type parameter which is not yet bound. We don't know what type to expect here. capnproto-c++-1.1.0/src/capnp/testdata/segmented0000644000175000017500000001262014527152321022344 0ustar00kentonkenton00000000000000|OO|…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšD»àÀ‚‹µÉGHJLNPRTVXZ\^fny{foo"barô€ LûNsè8¦3ZÒˆbÒ o!Ì_p ¯u@ !#%')19DFbaz"qux  nested :really nestedr  ) Þ€"ÒÒé€ÿ#Na¼@Ó ú€ÿÿÿ$yß †Hp.uýŠ–ýÿ€ÿÿÿÿÿÿÿ% "ÿ"Ò.ÿÿ #Na¼À,_ÿÿÿÿ"$yß †HpÒŠìuiÿÿÿÿÿÿÿÿ$%8´–I½ð|½ðüêê‚&4@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€(5,.0quux+*corge-2grault/:*468garply32waldo5*fred7"2 =@Cx structlist 1<zx structlist 2?zx structlist 3Bz:wE 0 I!o‘Kg+™ÔMÇkŸ9”`ùOÇqÄ+«uk9Ž;ÔTŠ”ðQoÞS5‚œ­UU¡®ÆW Çq¬µ¯˜2šY œ­E€€ÿÀ[$Àa¾@ððÿø]%aceplugh`2xyzzyb2thudd*_ikmoopsh"exhaustedjJrfc3092l:g ruxstructlist 1qjstructlist 2tjstructlist 3wjowzcapnproto-c++-1.1.0/src/capnp/testdata/annotated.json0000644000175000017500000000140114527152321023311 0ustar00kentonkenton00000000000000{ "names-can_contain!anything Really": "foo", "flatFoo": 123, "flatBar": "abc", "renamed-flatBaz": {"hello": true}, "flatQux": "cba", "pfx.foo": "this is a long string in order to force multi-line pretty printing", "pfx.renamed-bar": 321, "pfx.baz": {"hello": true}, "pfx.xfp.qux": "fed", "union-type": "renamed-bar", "barMember": 789, "multiMember": "ghi", "dependency": {"renamed-foo": "corge"}, "simpleGroup": {"renamed-grault": "garply"}, "enums": ["qux", "renamed-bar", "foo", "renamed-baz"], "innerJson": [123, "hello", {"object": true}], "testBase64": "ZnJlZA==", "testHex": "706c756768", "bUnion": "renamed-bar", "bValue": 678, "externalUnion": {"type": "bar", "value": "cba"}, "unionWithVoid": {"type": "voidValue"} } capnproto-c++-1.1.0/src/capnp/testdata/errors.capnp.nobuild0000644000175000017500000001046514527152321024445 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # This file is intended to test that various error cases are detected as errors. The error # output is matched against a golden file. The file name has the .nobuild extension to make # sure that a build system which automatically builds .capnp files does not try to build this one. # @0xccd0890aa4926a9b; # Can't really test the missing-ID error because the output is intentionally unpredictable. const notType :Int32 = 123; annotation notFieldAnnotation(struct) :Int32; annotation fieldAnnotation(field) :Int32; struct Foo { dupName @0 :Int32; dupName @1 :Int32; dupNumber1 @2 :Int32; dupNumber2 @2 :Int32; missingNumber @4 :Int32; next @5 :Int32; emptyUnion :union {} emptyGroup :group {} singletonUnion :union { field @6 :Int32; } union { dupName @7 :Int32; f8 @8 :Int32; } union { f9 @9 :Int32; f10 @10 :Int32; } struct wrongTypeStyle {} WrongFieldStyle @11 :Int32; under_score @12 :Int32; containsStruct :group { f13 @13 :Int32; struct CantNestHere {} } retroUnion @16! :union { f14 @14 :Int32; f15 @15 :Int32; } missingColonAndEclamation @18 union { f19 @19 :Int32; f20 @20 :Int32; } missingExclamation @21 :union { f22 @22 :Int32; f23 @23 :Int32; } missingColon @24! union { f19 @25 :Int32; f20 @26 :Int32; } unnamedInNamed :union { f27 @27 :Int32; f28 @28 :Int32; union { # content is ignored } } listWithoutParam @31 :List; listWithTooManyParams @32 :List(Int32, Int64); listAnyPointer @33 :List(AnyPointer); listAnyStruct @48 :List(AnyStruct); notAType @34 :notType; noParams @35 :Foo(Int32); defaultOutOfRange @36 :Int16 = 1234567; defaultOutOfRange2 @37 :UInt16 = -1; defaultWrongType @38 :Text = 123; defaultWrongType2 @39 :Text = [123]; defaultWrongType3 @40 :Text = (foo = 123, bar = 456); defaultTooBigToBeNegative @41 :Int64 = -0x8000000000000001; defaultNotConstant @42 :Int32 = .Foo; defaultConstantNotQualified @43 :Int32 = notType; notAnnotation @44 :Int32 $Foo(123); badAnnotation @45 :Int32 $notFieldAnnotation(123); notVoidAnnotation @46 :Int32 $fieldAnnotation; undefinedImport @17 :import "noshuchfile.capnp".Bar; undefinedAbsolute @47 : .NoSuch; undefinedRelative @29 :NoSuch; undefinedMember @30 :Foo.NoSuch; } struct Bar { x @3 :Text; someGroup :group { defaultMissingFieldName @2 :Bar = (x = "abcd", 456); defaultNoSuchField @0 :Bar = (nosuchfield = 123); defaultGroupMismatch @1 :Bar = (someGroup = 123); } } using Bar; enum DupEnumerants { dupName @0; dupName @1; dupNumber1 @2; dupNumber2 @2; } const recursive: UInt32 = .recursive; struct Generic(T, U) { foo @0 :UInt32 $T; } struct UseGeneric { tooFew @0 :Generic(Text); tooMany @1 :Generic(Text, Data, List(Int32)); doubleBind @2 :Generic(Text, Data)(Data, Text); primitiveBinding @3 :Generic(Text, Int32); } const embedBadType :UInt32 = embed "binary"; const embedNoSuchFile :Data = embed "no-such-file"; using Baz = import "nosuchfile-unused.capnp".Baz; # Check that an import in an unused `using` still reports error. interface TestInterface { foo @0 (a :UInt32 = null); bar @1 stream -> (); } capnproto-c++-1.1.0/src/capnp/testdata/errors2.capnp.nobuild0000644000175000017500000000306514527152321024525 0ustar00kentonkenton00000000000000# Copyright (c) 2020 Cloudflare, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xea7dcf0ca9acfa97; # This is much like errors.capnp.nobuild but expresses errors that occur in a later phase of # compilation, which is never reached when building errors.capnp.nobuild because the compiler # bails out after other errors. struct DummyType {} const dummyValue :DummyType = (); struct TestDefaultValueForGeneric(A) { single @0 :A = .dummyValue; nested @1 :Box(A) = (val = .dummyValue); } struct Box(B) { val @0 :B; } capnproto-c++-1.1.0/src/capnp/testdata/segmented-packed0000644000175000017500000000251014527152321023566 0ustar00kentonkenton00000000000000|OO|ÿ…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšDþ»àÀ‚‹µÉGHJLNPRTVXZ\^fny{foo"barÿô€ Lû?Nsè8¦3ýZÒˆbÿÒ o!Ì_p ¯àu@ !#%')19DFbaz"qux  ?nested :ÿreally nestedrP P ) Þ€"ïÒÒé€ÿ#÷Na¼@Ó úø€ÿÿÿ$?yß †Hpÿ.uýŠ–ýÿ€€ÿÿÿÿÿÿÿÿ% "ÿ"ÏÒ.ÿÿ #÷Na¼À,_ðÿÿÿÿ"$?yß †HpÒŠìuiÿÿÿÿÿÿÿÿÿ$%ð8´–Iÿ½ð|½ðüêê‚&4ÿ@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€(5,.0quux+*corge-2?grault/:*468?garply32waldo5*fred7"2Q =@Cÿx struct?list 1<zÿx struct?list 2?zÿx struct?list 3Bz:1wEP 0 I!o‘Kg+™ÔMÿÇkŸ9”`ùOÿÇqÄ+«uk9Ž;ÔTŠ”ðQoÞS5‚œ­UU¡®ÆW ÿÇq¬µ¯˜2šY Μ­E€Ì€ÿÀ[$ðÀa¾@ÀðÀðÿÀø]%aceplugh`2xyzzyb2thudd*_ikmoopsh"ÿexhaustedjJrfc3092l:gQ ruxÿstructlist 1qjÿstructlist 2tjÿstructlist 3wjo1wzPcapnproto-c++-1.1.0/src/capnp/testdata/short.txt0000644000175000017500000001021314527152321022342 0ustar00kentonkenton00000000000000(voidField = void, boolField = true, int8Field = -123, int16Field = -12345, int32Field = -12345678, int64Field = -123456789012345, uInt8Field = 234, uInt16Field = 45678, uInt32Field = 3456789012, uInt64Field = 12345678901234567890, float32Field = 1234.5, float64Field = -1.23e47, textField = "foo", dataField = "bar", structField = (voidField = void, boolField = true, int8Field = -12, int16Field = 3456, int32Field = -78901234, int64Field = 56789012345678, uInt8Field = 90, uInt16Field = 1234, uInt32Field = 56789012, uInt64Field = 345678901234567890, float32Field = -1.25e-10, float64Field = 345, textField = "baz", dataField = "qux", structField = (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "nested", structField = (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "really nested", enumField = foo, interfaceField = void), enumField = foo, interfaceField = void), enumField = baz, interfaceField = void, voidList = [void, void, void], boolList = [false, true, false, true, true], int8List = [12, -34, -128, 127], int16List = [1234, -5678, -32768, 32767], int32List = [12345678, -90123456, -2147483648, 2147483647], int64List = [123456789012345, -678901234567890, -9223372036854775808, 9223372036854775807], uInt8List = [12, 34, 0, 255], uInt16List = [1234, 5678, 0, 65535], uInt32List = [12345678, 90123456, 0, 4294967295], uInt64List = [123456789012345, 678901234567890, 0, 18446744073709551615], float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], textList = ["quux", "corge", "grault"], dataList = ["garply", "waldo", "fred"], structList = [(voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 1", enumField = foo, interfaceField = void), (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 2", enumField = foo, interfaceField = void), (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 3", enumField = foo, interfaceField = void)], enumList = [qux, bar, grault]), enumField = corge, interfaceField = void, voidList = [void, void, void, void, void, void], boolList = [true, false, false, true], int8List = [111, -111], int16List = [11111, -11111], int32List = [111111111, -111111111], int64List = [1111111111111111111, -1111111111111111111], uInt8List = [111, 222], uInt16List = [33333, 44444], uInt32List = [3333333333], uInt64List = [11111111111111111111], float32List = [5555.5, inf, -inf, nan], float64List = [7777.75, inf, -inf, nan], textList = ["plugh", "xyzzy", "thud"], dataList = ["oops", "exhausted", "rfc3092"], structList = [(voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 1", enumField = foo, interfaceField = void), (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 2", enumField = foo, interfaceField = void), (voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 3", enumField = foo, interfaceField = void)], enumList = [foo, garply]) capnproto-c++-1.1.0/src/capnp/testdata/errors.txt0000644000175000017500000001243314527152321022525 0ustar00kentonkenton00000000000000file:74:30-32: error: As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to unions. However, removing the number will break binary compatibility. If this is an old protocol and you need to retain compatibility, please add an exclamation point after the number to indicate that it is really needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility doesn't matter, just remove the @n entirely. Sorry for the inconvenience, and thanks for being an early adopter! :) file:74:30-32: error: As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon for named unions, e.g. `foo :union {`. file:79:23-25: error: As of Cap'n Proto v0.3, it is no longer necessary to assign numbers to unions. However, removing the number will break binary compatibility. If this is an old protocol and you need to retain compatibility, please add an exclamation point after the number to indicate that it is really needed, e.g. `foo @1! :union {`. If this is a new protocol or compatibility doesn't matter, just remove the @n entirely. Sorry for the inconvenience, and thanks for being an early adopter! :) file:84:17-19: error: As of Cap'n Proto v0.3, the 'union' keyword should be prefixed with a colon for named unions, e.g. `foo :union {`. file:133:7-10: error: 'using' declaration without '=' must specify a named declaration from a different scope. file:37:3-10: error: 'dupName' is already defined in this scope. file:36:3-10: error: 'dupName' previously defined here. file:52:5-12: error: 'dupName' is already defined in this scope. file:36:3-10: error: 'dupName' previously defined here. file:55:3-8: error: An unnamed union is already defined in this scope. file:51:3-8: error: Previously defined here. file:60:10-24: error: Type names must begin with a capital letter. file:61:3-18: error: Non-type names must begin with a lower-case letter. file:62:3-14: error: Cap'n Proto declaration names should use camelCase and must not contain underscores. (Code generators may convert names to the appropriate style for the target language.) file:66:5-27: error: This kind of declaration doesn't belong here. file:44:3-23: error: Union must have at least two members. file:45:3-23: error: Group must have at least one member. file:47: error: Union must have at least two members. file:92: error: Unions cannot contain unnamed unions. file:39:15-16: error: Duplicate ordinal number. file:38:15-16: error: Ordinal @2 originally used here. file:41:18-19: error: Skipped ordinal @3. Ordinals must be sequential with no holes. file:69:15-17: error: Union ordinal, if specified, must be greater than no more than one of its member ordinals (i.e. there can only be one field retroactively unionized). file:117:31-50: error: Import failed: noshuchfile.capnp file:119:26-32: error: Not defined: NoSuch file:120:28-34: error: 'Foo' has no member named 'NoSuch' file:97:25-29: error: 'List' requires exactly one parameter. file:98:30-48: error: Too many generic parameters. file:98:30-34: error: 'List' requires exactly one parameter. file:99:23-39: error: 'List(AnyPointer)' is not supported. file:101:17-24: error: 'notType' is not a type. file:102:17-27: error: Declaration does not accept generic parameters. file:104:34-41: error: Integer value out of range. file:105:37-38: error: Integer value out of range. file:106:32-35: error: Type mismatch; expected Text. file:107:33-38: error: Type mismatch; expected Text. file:108:33-55: error: Type mismatch; expected Text. file:109:43-61: error: Integer is too big to be negative. file:110:35-39: error: '.Foo' does not refer to a constant. file:111:44-51: error: Constant names must be qualified to avoid confusion. Please replace 'notType' with '.notType', if that's what you intended. file:118:28-34: error: Not defined: NoSuch file:100:22-37: error: 'List(AnyStruct)' is not supported. file:113:29-32: error: 'Foo' is not an annotation. file:114:29-47: error: 'notFieldAnnotation' cannot be applied to this kind of declaration. file:115:33-48: error: 'fieldAnnotation' requires a value. file:127:35-46: error: Struct has no field named 'nosuchfield'. file:128:49-52: error: Type mismatch; expected group. file:126:52-55: error: Missing field name. file:137:3-10: error: 'dupName' is already defined in this scope. file:136:3-10: error: 'dupName' previously defined here. file:139:15-16: error: Duplicate ordinal number. file:138:15-16: error: Ordinal @2 originally used here. file:142:7-16: error: Declaration recursively depends on itself. file:145:19-20: error: 'T' is not an annotation. file:149:14-27: error: Not enough generic parameters. file:150:15-47: error: Too many generic parameters. file:151:18-49: error: Double-application of generic parameters. file:152:38-43: error: Sorry, only pointer types can be used as generic parameters. file:155:30-44: error: Embeds can only be used when Text, Data, or a struct is expected. file:156:37-51: error: Couldn't read file for embed: no-such-file file:162:23-27: error: Only pointer parameters can declare their default as 'null'. file:163:10-16: error: 'stream' can only appear after '->', not before. file:163:10-16: error: A method declaration uses streaming, but '/capnp/stream.capnp' is not found in the import path. This is a standard file that should always be installed with the Cap'n Proto compiler. file:158:20-45: error: Import failed: nosuchfile-unused.capnp capnproto-c++-1.1.0/src/capnp/testdata/packedflat0000644000175000017500000000147414527152321022474 0ustar00kentonkenton00000000000000Pÿ…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšDþ»àÀ‚‹µÉM"MQL…0!……… … …$‰%•©3Áwfoobarÿô€ Lû?Nsè8¦3ýZÒˆbÿÒ o!Ì_p ¯àu@M"MQL%!)!"!#!$%%1"1#1$5%A4I5]q3…wÕbazquxM:QH?nestedMrÿreally nested Þ€ïÒÒé€ÿ÷Na¼@Ó úø€ÿÿÿ?yß †Hpÿ.uýŠ–ýÿ€€ÿÿÿÿÿÿÿÿ "ÿÏÒ.ÿÿ÷Na¼À,_ðÿÿÿÿ?yß †HpÒŠìuiÿÿÿÿÿÿÿÿÿð8´–Iÿ½ð|½ðüêê‚ÿ@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€ * 2 :quuxcorge?grault 2 * "?garplywaldofredQ z½z]zÿx struct?list 1ÿx struct?list 2ÿx struct?list 3 o‘g+™ÔÿÇkŸ9”`ùÇqÄ+«uk9Ž;ÔTŠ”ðoÞ5‚œ­U¡®ÆÿÇq¬µ¯˜2šÎœ­E€Ì€ÿÀðÀa¾@ÀðÀðÿÀø 2 2 *plughxyzzythud " J :oopsÿexhaustedrfc3092Q j½j]jÿstructlist 1ÿstructlist 2ÿstructlist 3capnproto-c++-1.1.0/src/capnp/testdata/pretty.json0000644000175000017500000001174614527152321022700 0ustar00kentonkenton00000000000000{ "voidField": null, "boolField": true, "int8Field": -123, "int16Field": -12345, "int32Field": -12345678, "int64Field": "-123456789012345", "uInt8Field": 234, "uInt16Field": 45678, "uInt32Field": 3456789012, "uInt64Field": "12345678901234567890", "float32Field": 1234.5, "float64Field": -1.23e47, "textField": "foo", "dataField": [98, 97, 114], "structField": { "voidField": null, "boolField": true, "int8Field": -12, "int16Field": 3456, "int32Field": -78901234, "int64Field": "56789012345678", "uInt8Field": 90, "uInt16Field": 1234, "uInt32Field": 56789012, "uInt64Field": "345678901234567890", "float32Field": -1.2499999646475857e-10, "float64Field": 345, "textField": "baz", "dataField": [113, 117, 120], "structField": { "voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "nested", "structField": {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "really nested", "enumField": "foo", "interfaceField": null}, "enumField": "foo", "interfaceField": null }, "enumField": "baz", "interfaceField": null, "voidList": [null, null, null], "boolList": [false, true, false, true, true], "int8List": [12, -34, -128, 127], "int16List": [1234, -5678, -32768, 32767], "int32List": [12345678, -90123456, -2147483648, 2147483647], "int64List": ["123456789012345", "-678901234567890", "-9223372036854775808", "9223372036854775807"], "uInt8List": [12, 34, 0, 255], "uInt16List": [1234, 5678, 0, 65535], "uInt32List": [12345678, 90123456, 0, 4294967295], "uInt64List": ["123456789012345", "678901234567890", "0", "18446744073709551615"], "float32List": [0, 1234567, 9.9999999338158125e36, -9.9999999338158125e36, 9.99999991097579e-38, -9.99999991097579e-38], "float64List": [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], "textList": ["quux", "corge", "grault"], "dataList": [[103, 97, 114, 112, 108, 121], [119, 97, 108, 100, 111], [102, 114, 101, 100]], "structList": [ {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "x structlist 1", "enumField": "foo", "interfaceField": null}, {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "x structlist 2", "enumField": "foo", "interfaceField": null}, {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "x structlist 3", "enumField": "foo", "interfaceField": null} ], "enumList": ["qux", "bar", "grault"] }, "enumField": "corge", "interfaceField": null, "voidList": [null, null, null, null, null, null], "boolList": [true, false, false, true], "int8List": [111, -111], "int16List": [11111, -11111], "int32List": [111111111, -111111111], "int64List": ["1111111111111111111", "-1111111111111111111"], "uInt8List": [111, 222], "uInt16List": [33333, 44444], "uInt32List": [3333333333], "uInt64List": ["11111111111111111111"], "float32List": [5555.5, "Infinity", "-Infinity", "NaN"], "float64List": [7777.75, "Infinity", "-Infinity", "NaN"], "textList": ["plugh", "xyzzy", "thud"], "dataList": [[111, 111, 112, 115], [101, 120, 104, 97, 117, 115, 116, 101, 100], [114, 102, 99, 51, 48, 57, 50]], "structList": [ {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "structlist 1", "enumField": "foo", "interfaceField": null}, {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "structlist 2", "enumField": "foo", "interfaceField": null}, {"voidField": null, "boolField": false, "int8Field": 0, "int16Field": 0, "int32Field": 0, "int64Field": "0", "uInt8Field": 0, "uInt16Field": 0, "uInt32Field": 0, "uInt64Field": "0", "float32Field": 0, "float64Field": 0, "textField": "structlist 3", "enumField": "foo", "interfaceField": null} ], "enumList": ["foo", "garply"] } capnproto-c++-1.1.0/src/capnp/testdata/packed0000644000175000017500000000147714527152321021630 0ustar00kentonkenton000000000000000_Pÿ…ÇϲžCÿ‡ òy·ÿÿên²j ÎÒ 댩T«PšDþ»àÀ‚‹µÉM"MQL…0!……… … …$‰%•©3Áwfoobarÿô€ Lû?Nsè8¦3ýZÒˆbÿÒ o!Ì_p ¯àu@M"MQL%!)!"!#!$%%1"1#1$5%A4I5]q3…wÕbazquxM:QH?nestedMrÿreally nested Þ€ïÒÒé€ÿ÷Na¼@Ó úø€ÿÿÿ?yß †Hpÿ.uýŠ–ýÿ€€ÿÿÿÿÿÿÿÿ "ÿÏÒ.ÿÿ÷Na¼À,_ðÿÿÿÿ?yß †HpÒŠìuiÿÿÿÿÿÿÿÿÿð8´–Iÿ½ð|½ðüêê‚ÿ@Þwƒ!ÜB)#ÊåÈv)#ÊåÈvÿ‘÷P7žxf‘÷P7žxf€ * 2 :quuxcorge?grault 2 * "?garplywaldofredQ z½z]zÿx struct?list 1ÿx struct?list 2ÿx struct?list 3 o‘g+™ÔÿÇkŸ9”`ùÇqÄ+«uk9Ž;ÔTŠ”ðoÞ5‚œ­U¡®ÆÿÇq¬µ¯˜2šÎœ­E€Ì€ÿÀðÀa¾@ÀðÀðÿÀø 2 2 *plughxyzzythud " J :oopsÿexhaustedrfc3092Q j½j]jÿstructlist 1ÿstructlist 2ÿstructlist 3capnproto-c++-1.1.0/src/capnp/testdata/lists.binary0000644000175000017500000000211014527152321023003 0ustar00kentonkenton00000000000000ˆ %%'5=EMUe}­{-90…Í[Ò8û ÀºŠ<Õb‡KªíaU""foobar   òO¼ ""foobar"baz"2quxcorge§Õ×{Ècapnproto-c++-1.1.0/src/capnp/testdata/pretty.txt0000644000175000017500000001225114527152321022536 0ustar00kentonkenton00000000000000( voidField = void, boolField = true, int8Field = -123, int16Field = -12345, int32Field = -12345678, int64Field = -123456789012345, uInt8Field = 234, uInt16Field = 45678, uInt32Field = 3456789012, uInt64Field = 12345678901234567890, float32Field = 1234.5, float64Field = -1.23e47, textField = "foo", dataField = "bar", structField = ( voidField = void, boolField = true, int8Field = -12, int16Field = 3456, int32Field = -78901234, int64Field = 56789012345678, uInt8Field = 90, uInt16Field = 1234, uInt32Field = 56789012, uInt64Field = 345678901234567890, float32Field = -1.25e-10, float64Field = 345, textField = "baz", dataField = "qux", structField = ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "nested", structField = ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "really nested", enumField = foo, interfaceField = void ), enumField = foo, interfaceField = void ), enumField = baz, interfaceField = void, voidList = [void, void, void], boolList = [false, true, false, true, true], int8List = [12, -34, -128, 127], int16List = [1234, -5678, -32768, 32767], int32List = [12345678, -90123456, -2147483648, 2147483647], int64List = [123456789012345, -678901234567890, -9223372036854775808, 9223372036854775807], uInt8List = [12, 34, 0, 255], uInt16List = [1234, 5678, 0, 65535], uInt32List = [12345678, 90123456, 0, 4294967295], uInt64List = [123456789012345, 678901234567890, 0, 18446744073709551615], float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], textList = ["quux", "corge", "grault"], dataList = ["garply", "waldo", "fred"], structList = [ ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 1", enumField = foo, interfaceField = void ), ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 2", enumField = foo, interfaceField = void ), ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "x structlist 3", enumField = foo, interfaceField = void ) ], enumList = [qux, bar, grault] ), enumField = corge, interfaceField = void, voidList = [void, void, void, void, void, void], boolList = [true, false, false, true], int8List = [111, -111], int16List = [11111, -11111], int32List = [111111111, -111111111], int64List = [1111111111111111111, -1111111111111111111], uInt8List = [111, 222], uInt16List = [33333, 44444], uInt32List = [3333333333], uInt64List = [11111111111111111111], float32List = [5555.5, inf, -inf, nan], float64List = [7777.75, inf, -inf, nan], textList = ["plugh", "xyzzy", "thud"], dataList = ["oops", "exhausted", "rfc3092"], structList = [ ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 1", enumField = foo, interfaceField = void ), ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 2", enumField = foo, interfaceField = void ), ( voidField = void, boolField = false, int8Field = 0, int16Field = 0, int32Field = 0, int64Field = 0, uInt8Field = 0, uInt16Field = 0, uInt32Field = 0, uInt64Field = 0, float32Field = 0, float64Field = 0, textField = "structlist 3", enumField = foo, interfaceField = void ) ], enumList = [foo, garply] ) capnproto-c++-1.1.0/src/capnp/schema.capnp0000644000175000017500000004543614731420004021124 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. using Cxx = import "/capnp/c++.capnp"; @0xa93fc509624c72d9; $Cxx.namespace("capnp::schema"); using Id = UInt64; # The globally-unique ID of a file, type, or annotation. struct Node { id @0 :Id; displayName @1 :Text; # Name to present to humans to identify this Node. You should not attempt to parse this. Its # format could change. It is not guaranteed to be unique. # # (On Zooko's triangle, this is the node's nickname.) displayNamePrefixLength @2 :UInt32; # If you want a shorter version of `displayName` (just naming this node, without its surrounding # scope), chop off this many characters from the beginning of `displayName`. scopeId @3 :Id; # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not # listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is # zero if the node has no parent, which is normally only the case with files, but should be # allowed for any kind of node (in order to make runtime type generation easier). parameters @32 :List(Parameter); # If this node is parameterized (generic), the list of parameters. Empty for non-generic types. isGeneric @33 :Bool; # True if this node is generic, meaning that it or one of its parent scopes has a non-empty # `parameters`. struct Parameter { # Information about one of the node's parameters. name @0 :Text; } nestedNodes @4 :List(NestedNode); # List of nodes nested within this node, along with the names under which they were declared. struct NestedNode { name @0 :Text; # Unqualified symbol name. Unlike Node.displayName, this *can* be used programmatically. # # (On Zooko's triangle, this is the node's petname according to its parent scope.) id @1 :Id; # ID of the nested node. Typically, the target node's scopeId points back to this node, but # robust code should avoid relying on this. } annotations @5 :List(Annotation); # Annotations applied to this node. union { # Info specific to each kind of node. file @6 :Void; struct :group { dataWordCount @7 :UInt16; # Size of the data section, in words. pointerCount @8 :UInt16; # Size of the pointer section, in pointers (which are one word each). preferredListEncoding @9 :ElementSize; # The preferred element size to use when encoding a list of this struct. If this is anything # other than `inlineComposite` then the struct is one word or less in size and is a candidate # for list packing optimization. isGroup @10 :Bool; # If true, then this "struct" node is actually not an independent node, but merely represents # some named union or group within a particular parent struct. This node's scopeId refers # to the parent struct, which may itself be a union/group in yet another struct. # # All group nodes share the same dataWordCount and pointerCount as the top-level # struct, and their fields live in the same ordinal and offset spaces as all other fields in # the struct. # # Note that a named union is considered a special kind of group -- in fact, a named union # is exactly equivalent to a group that contains nothing but an unnamed union. discriminantCount @11 :UInt16; # Number of fields in this struct which are members of an anonymous union, and thus may # overlap. If this is non-zero, then a 16-bit discriminant is present indicating which # of the overlapping fields is active. This can never be 1 -- if it is non-zero, it must be # two or more. # # Note that the fields of an unnamed union are considered fields of the scope containing the # union -- an unnamed union is not its own group. So, a top-level struct may contain a # non-zero discriminant count. Named unions, on the other hand, are equivalent to groups # containing unnamed unions. So, a named union has its own independent schema node, with # `isGroup` = true. discriminantOffset @12 :UInt32; # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in # multiples of 16 bits. fields @13 :List(Field); # Fields defined within this scope (either the struct's top-level fields, or the fields of # a particular group; see `isGroup`). # # The fields are sorted by ordinal number, but note that because groups share the same # ordinal space, the field's index in this list is not necessarily exactly its ordinal. # On the other hand, the field's position in this list does remain the same even as the # protocol evolves, since it is not possible to insert or remove an earlier ordinal. # Therefore, for most use cases, if you want to identify a field by number, it may make the # most sense to use the field's index in this list rather than its ordinal. } enum :group { enumerants@14 :List(Enumerant); # Enumerants ordered by numeric value (ordinal). } interface :group { methods @15 :List(Method); # Methods ordered by ordinal. superclasses @31 :List(Superclass); # Superclasses of this interface. } const :group { type @16 :Type; value @17 :Value; } annotation :group { type @18 :Type; targetsFile @19 :Bool; targetsConst @20 :Bool; targetsEnum @21 :Bool; targetsEnumerant @22 :Bool; targetsStruct @23 :Bool; targetsField @24 :Bool; targetsUnion @25 :Bool; targetsGroup @26 :Bool; targetsInterface @27 :Bool; targetsMethod @28 :Bool; targetsParam @29 :Bool; targetsAnnotation @30 :Bool; } } startByte @34 :UInt32; endByte @35 :UInt32; struct SourceInfo { # Additional information about a node which is not needed at runtime, but may be useful for # documentation or debugging purposes. This is kept in a separate struct to make sure it # doesn't accidentally get included in contexts where it is not needed. The # `CodeGeneratorRequest` includes this information in a separate array. id @0 :Id; # ID of the Node which this info describes. docComment @1 :Text; # The top-level doc comment for the Node. members @2 :List(Member); # Information about each member -- i.e. fields (for structs), enumerants (for enums), or # methods (for interfaces). # # This list is the same length and order as the corresponding list in the Node, i.e. # Node.struct.fields, Node.enum.enumerants, or Node.interface.methods. struct Member { docComment @0 :Text; # Doc comment on the member. } startByte @3 :UInt32; endByte @4 :UInt32; } } struct Field { # Schema for a field of a struct. name @0 :Text; codeOrder @1 :UInt16; # Indicates where this member appeared in the code, relative to other members. # Code ordering may have semantic relevance -- programmers tend to place related fields # together. So, using code ordering makes sense in human-readable formats where ordering is # otherwise irrelevant, like JSON. The values of codeOrder are tightly-packed, so the maximum # value is count(members) - 1. Fields that are members of a union are only ordered relative to # the other members of that union, so the maximum value there is count(union.members). annotations @2 :List(Annotation); const noDiscriminant :UInt16 = 0xffff; discriminantValue @3 :UInt16 = Field.noDiscriminant; # If the field is in a union, this is the value which the union's discriminant should take when # the field is active. If the field is not in a union, this is 0xffff. union { slot :group { # A regular, non-group, non-fixed-list field. offset @4 :UInt32; # Offset, in units of the field's size, from the beginning of the section in which the field # resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the # beginning of the data section. type @5 :Type; defaultValue @6 :Value; hadExplicitDefault @10 :Bool; # Whether the default value was specified explicitly. Non-explicit default values are always # zero or empty values. Usually, whether the default value was explicit shouldn't matter. # The main use case for this flag is for structs representing method parameters: # explicitly-defaulted parameters may be allowed to be omitted when calling the method. } group :group { # A group. typeId @7 :Id; # The ID of the group's node. } } ordinal :union { implicit @8 :Void; explicit @9 :UInt16; # The original ordinal number given to the field. You probably should NOT use this; if you need # a numeric identifier for a field, use its position within the field array for its scope. # The ordinal is given here mainly just so that the original schema text can be reproduced given # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job. } } struct Enumerant { # Schema for member of an enum. name @0 :Text; codeOrder @1 :UInt16; # Specifies order in which the enumerants were declared in the code. # Like Struct.Field.codeOrder. annotations @2 :List(Annotation); } struct Superclass { id @0 :Id; brand @1 :Brand; } struct Method { # Schema for method of an interface. name @0 :Text; codeOrder @1 :UInt16; # Specifies order in which the methods were declared in the code. # Like Struct.Field.codeOrder. implicitParameters @7 :List(Node.Parameter); # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended # to be inferred rather than specified explicitly, although not all languages support this. paramStructType @2 :Id; # ID of the parameter struct type. If a named parameter list was specified in the method # declaration (rather than a single struct parameter type) then a corresponding struct type is # auto-generated. Such an auto-generated type will not be listed in the interface's # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace. # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes # this a situation where you can't just climb the scope chain to find where a particular # generic parameter was introduced. Making the `scopeId` zero was a mistake.) paramBrand @5 :Brand; # Brand of param struct type. resultStructType @3 :Id; # ID of the return struct type; similar to `paramStructType`. resultBrand @6 :Brand; # Brand of result struct type. annotations @4 :List(Annotation); } struct Type { # Represents a type expression. union { # The ordinals intentionally match those of Value. void @0 :Void; bool @1 :Void; int8 @2 :Void; int16 @3 :Void; int32 @4 :Void; int64 @5 :Void; uint8 @6 :Void; uint16 @7 :Void; uint32 @8 :Void; uint64 @9 :Void; float32 @10 :Void; float64 @11 :Void; text @12 :Void; data @13 :Void; list :group { elementType @14 :Type; } enum :group { typeId @15 :Id; brand @21 :Brand; } struct :group { typeId @16 :Id; brand @22 :Brand; } interface :group { typeId @17 :Id; brand @23 :Brand; } anyPointer :union { unconstrained :union { # A regular AnyPointer. # # The name "unconstrained" means as opposed to constraining it to match a type parameter. # In retrospect this name is probably a poor choice given that it may still be constrained # to be a struct, list, or capability. anyKind @18 :Void; # truly AnyPointer struct @25 :Void; # AnyStruct list @26 :Void; # AnyList capability @27 :Void; # Capability } parameter :group { # This is actually a reference to a type parameter defined within this scope. scopeId @19 :Id; # ID of the generic type whose parameter we're referencing. This should be a parent of the # current scope. parameterIndex @20 :UInt16; # Index of the parameter within the generic type's parameter list. } implicitMethodParameter :group { # This is actually a reference to an implicit (generic) parameter of a method. The only # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand. parameterIndex @24 :UInt16; } } } } struct Brand { # Specifies bindings for parameters of generics. Since these bindings turn a generic into a # non-generic, we call it the "brand". scopes @0 :List(Scope); # For each of the target type and each of its parent scopes, a parameterization may be included # in this list. If no parameterization is included for a particular relevant scope, then either # that scope has no parameters or all parameters should be considered to be `AnyPointer`. struct Scope { scopeId @0 :Id; # ID of the scope to which these params apply. union { bind @1 :List(Binding); # List of parameter bindings. inherit @2 :Void; # The place where the Brand appears is within this scope or a sub-scope, and bindings # for this scope are deferred to later Brand applications. This is equivalent to a # pass-through binding list, where each of this scope's parameters is bound to itself. # For example: # # struct Outer(T) { # struct Inner { # value @0 :T; # } # innerInherit @0 :Inner; # Outer Brand.Scope is `inherit`. # innerBindSelf @1 :Outer(T).Inner; # Outer Brand.Scope explicitly binds T to T. # } # # The innerInherit and innerBindSelf fields have equivalent types, but different Brand # styles. } } struct Binding { union { unbound @0 :Void; type @1 :Type; # TODO(someday): Allow non-type parameters? Unsure if useful. } } } struct Value { # Represents a value, e.g. a field default value, constant value, or annotation value. union { # The ordinals intentionally match those of Type. void @0 :Void; bool @1 :Bool; int8 @2 :Int8; int16 @3 :Int16; int32 @4 :Int32; int64 @5 :Int64; uint8 @6 :UInt8; uint16 @7 :UInt16; uint32 @8 :UInt32; uint64 @9 :UInt64; float32 @10 :Float32; float64 @11 :Float64; text @12 :Text; data @13 :Data; list @14 :AnyPointer; enum @15 :UInt16; struct @16 :AnyPointer; interface @17 :Void; # The only interface value that can be represented statically is "null", whose methods always # throw exceptions. anyPointer @18 :AnyPointer; } } struct Annotation { # Describes an annotation applied to a declaration. Note AnnotationNode describes the # annotation's declaration, while this describes a use of the annotation. id @0 :Id; # ID of the annotation node. brand @2 :Brand; # Brand of the annotation. # # Note that the annotation itself is not allowed to be parameterized, but its scope might be. value @1 :Value; } enum ElementSize { # Possible element sizes for encoded lists. These correspond exactly to the possible values of # the 3-bit element size component of a list pointer. empty @0; # aka "void", but that's a keyword. bit @1; byte @2; twoBytes @3; fourBytes @4; eightBytes @5; pointer @6; inlineComposite @7; } struct CapnpVersion { major @0 :UInt16; minor @1 :UInt8; micro @2 :UInt8; } struct CodeGeneratorRequest { capnpVersion @2 :CapnpVersion; # Version of the `capnp` executable. Generally, code generators should ignore this, but the code # generators that ship with `capnp` itself will print a warning if this mismatches since that # probably indicates something is misconfigured. # # The first version of 'capnp' to set this was 0.6.0. So, if it's missing, the compiler version # is older than that. nodes @0 :List(Node); # All nodes parsed by the compiler, including for the files on the command line and their # imports. sourceInfo @3 :List(Node.SourceInfo); # Information about the original source code for each node, where available. This array may be # omitted or may be missing some nodes if no info is available for them. requestedFiles @1 :List(RequestedFile); # Files which were listed on the command line. struct RequestedFile { id @0 :Id; # ID of the file. filename @1 :Text; # Name of the file as it appeared on the command-line (minus the src-prefix). You may use # this to decide where to write the output. imports @2 :List(Import); # List of all imported paths seen in this file. struct Import { id @0 :Id; # ID of the imported file. name @1 :Text; # Name which *this* file used to refer to the foreign file. This may be a relative name. # This information is provided because it might be useful for code generation, e.g. to # generate #include directives in C++. We don't put this in Node.file because this # information is only meaningful at compile time anyway. # # (On Zooko's triangle, this is the import's petname according to the importing file.) } fileSourceInfo @3 :FileSourceInfo; struct FileSourceInfo { identifiers @0 :List(Identifier); struct Identifier { startByte @0 :UInt32; endByte @1 :UInt32; union { typeId @2 :UInt64; # Identifier refers to a type. This is the type ID. member :group { # Identifier refers to a member of a type. parentTypeId @3 :UInt64; ordinal @4 :UInt16; } } } } } } capnproto-c++-1.1.0/src/capnp/schema.c++0000644000175000017500000010120714712011043020356 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "schema.h" #include "message.h" #include #include namespace capnp { namespace schema { uint KJ_HASHCODE(Type::Which w) { return kj::hashCode(static_cast(w)); } // TODO(cleanup): Cap'n Proto does not declare stringifiers nor hashers for `Which` enums, unlike // all other enums. Fix that and remove this. } namespace _ { // private // Null schemas generated using the below schema file with: // // capnp eval -Isrc null-schemas.capnp node --flat | // hexdump -v -e '8/1 "0x%02x, "' -e '1/8 "\n"'; echo // // I totally don't understand hexdump format strings and came up with this command based on trial // and error. // // @0x879863d4b2cc4a1e; // // using Node = import "/capnp/schema.capnp".Node; // // const node :Node = ( // id = 0x0000000000000000, // displayName = "(null schema)"); // // const struct :Node = ( // id = 0x0000000000000001, // displayName = "(null struct schema)", // struct = ( // dataWordCount = 0, // pointerCount = 0, // preferredListEncoding = empty)); // // const enum :Node = ( // id = 0x0000000000000002, // displayName = "(null enum schema)", // enum = ()); // // const interface :Node = ( // id = 0x0000000000000003, // displayName = "(null interface schema)", // interface = ()); // // const const :Node = ( // id = 0x0000000000000004, // displayName = "(null const schema)", // const = (type = (void = void), value = (void = void))); static const AlignedData<13> NULL_SCHEMA_BYTES = {{ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, // union discriminant intentionally mangled 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, }}; const RawSchema NULL_SCHEMA = { 0x0000000000000000, NULL_SCHEMA_BYTES.words, 13, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &NULL_SCHEMA, nullptr, nullptr, 0, 0, nullptr } }; static const AlignedData<14> NULL_STRUCT_SCHEMA_BYTES = {{ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, }}; const RawSchema NULL_STRUCT_SCHEMA = { 0x0000000000000001, NULL_STRUCT_SCHEMA_BYTES.words, 14, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &NULL_STRUCT_SCHEMA, nullptr, nullptr, 0, 0, nullptr } }; static const AlignedData<14> NULL_ENUM_SCHEMA_BYTES = {{ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; const RawSchema NULL_ENUM_SCHEMA = { 0x0000000000000002, NULL_ENUM_SCHEMA_BYTES.words, 14, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &NULL_ENUM_SCHEMA, nullptr, nullptr, 0, 0, nullptr } }; static const AlignedData<14> NULL_INTERFACE_SCHEMA_BYTES = {{ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, }}; const RawSchema NULL_INTERFACE_SCHEMA = { 0x0000000000000003, NULL_INTERFACE_SCHEMA_BYTES.words, 14, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &NULL_INTERFACE_SCHEMA, nullptr, nullptr, 0, 0, nullptr } }; static const AlignedData<20> NULL_CONST_SCHEMA_BYTES = {{ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; const RawSchema NULL_CONST_SCHEMA = { 0x0000000000000004, NULL_CONST_SCHEMA_BYTES.words, 20, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &NULL_CONST_SCHEMA, nullptr, nullptr, 0, 0, nullptr } }; } // namespace _ (private) // ======================================================================================= schema::Node::Reader Schema::getProto() const { return readMessageUnchecked(raw->generic->encodedNode); } kj::ArrayPtr Schema::asUncheckedMessage() const { return kj::arrayPtr(raw->generic->encodedNode, raw->generic->encodedSize); } Schema Schema::getDependency(uint64_t id, uint location) const { { // Binary search dependency list. uint lower = 0; uint upper = raw->dependencyCount; while (lower < upper) { uint mid = (lower + upper) / 2; auto candidate = raw->dependencies[mid]; if (candidate.location == location) { candidate.schema->ensureInitialized(); return Schema(candidate.schema); } else if (candidate.location < location) { lower = mid + 1; } else { upper = mid; } } } { uint lower = 0; uint upper = raw->generic->dependencyCount; while (lower < upper) { uint mid = (lower + upper) / 2; const _::RawSchema* candidate = raw->generic->dependencies[mid]; uint64_t candidateId = candidate->id; if (candidateId == id) { candidate->ensureInitialized(); return Schema(&candidate->defaultBrand); } else if (candidateId < id) { lower = mid + 1; } else { upper = mid; } } } KJ_FAIL_REQUIRE("Requested ID not found in dependency table.", kj::hex(id)) { return Schema(); } } Schema::BrandArgumentList Schema::getBrandArgumentsAtScope(uint64_t scopeId) const { KJ_REQUIRE(getProto().getIsGeneric(), "Not a generic type.", getProto().getDisplayName()); for (auto scope: kj::range(raw->scopes, raw->scopes + raw->scopeCount)) { if (scope->typeId == scopeId) { // OK, this scope matches the scope we're looking for. if (scope->isUnbound) { return BrandArgumentList(scopeId, true); } else { return BrandArgumentList(scopeId, scope->bindingCount, scope->bindings); } } } // This scope is not listed in the scopes list. return BrandArgumentList(scopeId, raw->isUnbound()); } kj::Array Schema::getGenericScopeIds() const { if (!getProto().getIsGeneric()) return nullptr; auto result = kj::heapArray(raw->scopeCount); for (auto iScope: kj::indices(result)) { result[iScope] = raw->scopes[iScope].typeId; } return result; } StructSchema Schema::asStruct() const { KJ_REQUIRE(getProto().isStruct(), "Tried to use non-struct schema as a struct.", getProto().getDisplayName()) { return StructSchema(); } return StructSchema(*this); } EnumSchema Schema::asEnum() const { KJ_REQUIRE(getProto().isEnum(), "Tried to use non-enum schema as an enum.", getProto().getDisplayName()) { return EnumSchema(); } return EnumSchema(*this); } InterfaceSchema Schema::asInterface() const { KJ_REQUIRE(getProto().isInterface(), "Tried to use non-interface schema as an interface.", getProto().getDisplayName()) { return InterfaceSchema(); } return InterfaceSchema(*this); } ConstSchema Schema::asConst() const { KJ_REQUIRE(getProto().isConst(), "Tried to use non-constant schema as a constant.", getProto().getDisplayName()) { return ConstSchema(); } return ConstSchema(*this); } kj::StringPtr Schema::getShortDisplayName() const { auto proto = getProto(); return proto.getDisplayName().slice(proto.getDisplayNamePrefixLength()); } const kj::StringPtr Schema::getUnqualifiedName() const { auto proto = getProto(); return proto.getDisplayName().slice(proto.getDisplayNamePrefixLength()); } void Schema::requireUsableAs(const _::RawSchema* expected) const { KJ_REQUIRE(raw->generic == expected || (expected != nullptr && raw->generic->canCastTo == expected), "This schema is not compatible with the requested native type."); } uint32_t Schema::getSchemaOffset(const schema::Value::Reader& value) const { const word* ptr; switch (value.which()) { case schema::Value::TEXT: ptr = reinterpret_cast(value.getText().begin()); break; case schema::Value::DATA: ptr = reinterpret_cast(value.getData().begin()); break; case schema::Value::STRUCT: ptr = value.getStruct().getAs<_::UncheckedMessage>(); break; case schema::Value::LIST: ptr = value.getList().getAs<_::UncheckedMessage>(); break; case schema::Value::ANY_POINTER: ptr = value.getAnyPointer().getAs<_::UncheckedMessage>(); break; default: KJ_FAIL_ASSERT("getDefaultValueSchemaOffset() can only be called on struct, list, " "and any-pointer fields."); } return ptr - raw->generic->encodedNode; } Type Schema::getBrandBinding(uint64_t scopeId, uint index) const { return getBrandArgumentsAtScope(scopeId)[index]; } Type Schema::interpretType(schema::Type::Reader proto, uint location) const { switch (proto.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: return proto.which(); case schema::Type::STRUCT: { auto structType = proto.getStruct(); return getDependency(structType.getTypeId(), location).asStruct(); } case schema::Type::ENUM: { auto enumType = proto.getEnum(); return getDependency(enumType.getTypeId(), location).asEnum(); } case schema::Type::INTERFACE: { auto interfaceType = proto.getInterface(); return getDependency(interfaceType.getTypeId(), location).asInterface(); } case schema::Type::LIST: return ListSchema::of(interpretType(proto.getList().getElementType(), location)); case schema::Type::ANY_POINTER: { auto anyPointer = proto.getAnyPointer(); switch (anyPointer.which()) { case schema::Type::AnyPointer::UNCONSTRAINED: return anyPointer.getUnconstrained().which(); case schema::Type::AnyPointer::PARAMETER: { auto param = anyPointer.getParameter(); return getBrandBinding(param.getScopeId(), param.getParameterIndex()); } case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: return Type(Type::ImplicitParameter { anyPointer.getImplicitMethodParameter().getParameterIndex() }); } KJ_UNREACHABLE; } } KJ_UNREACHABLE; } Type Schema::BrandArgumentList::operator[](uint index) const { if (isUnbound) { return Type::BrandParameter { scopeId, index }; } if (index >= size_) { // Binding index out-of-range. Treat as AnyPointer. This is important to allow new // type parameters to be added to existing types without breaking dependent // schemas. return schema::Type::ANY_POINTER; } auto& binding = bindings[index]; Type result; if (binding.which == (uint)schema::Type::ANY_POINTER) { if (binding.scopeId != 0) { result = Type::BrandParameter { binding.scopeId, binding.paramIndex }; } else if (binding.isImplicitParameter) { result = Type::ImplicitParameter { binding.paramIndex }; } else { result = static_cast(binding.paramIndex); } } else if (binding.schema == nullptr) { // Builtin / primitive type. result = static_cast(binding.which); } else { binding.schema->ensureInitialized(); result = Type(static_cast(binding.which), binding.schema); } return result.wrapInList(binding.listDepth); } kj::StringPtr KJ_STRINGIFY(const Schema& schema) { return schema.getProto().getDisplayName(); } // ======================================================================================= namespace { template auto findSchemaMemberByName(const _::RawSchema* raw, kj::StringPtr name, List&& list) -> kj::Maybe { uint lower = 0; uint upper = raw->memberCount; while (lower < upper) { uint mid = (lower + upper) / 2; uint16_t memberIndex = raw->membersByName[mid]; auto candidate = list[memberIndex]; kj::StringPtr candidateName = candidate.getProto().getName(); if (candidateName == name) { return candidate; } else if (candidateName < name) { lower = mid + 1; } else { upper = mid; } } return nullptr; } } // namespace StructSchema::FieldList StructSchema::getFields() const { return FieldList(*this, getProto().getStruct().getFields()); } StructSchema::FieldSubset StructSchema::getUnionFields() const { auto proto = getProto().getStruct(); return FieldSubset(*this, proto.getFields(), raw->generic->membersByDiscriminant, proto.getDiscriminantCount()); } StructSchema::FieldSubset StructSchema::getNonUnionFields() const { auto proto = getProto().getStruct(); auto fields = proto.getFields(); auto offset = proto.getDiscriminantCount(); auto size = fields.size() - offset; return FieldSubset(*this, fields, raw->generic->membersByDiscriminant + offset, size); } kj::Maybe StructSchema::findFieldByName(kj::StringPtr name) const { return findSchemaMemberByName(raw->generic, name, getFields()); } StructSchema::Field StructSchema::getFieldByName(kj::StringPtr name) const { KJ_IF_MAYBE(member, findFieldByName(name)) { return *member; } else { KJ_FAIL_REQUIRE("struct has no such member", name); } } kj::Maybe StructSchema::getFieldByDiscriminant(uint16_t discriminant) const { auto unionFields = getUnionFields(); if (discriminant >= unionFields.size()) { return nullptr; } else { return unionFields[discriminant]; } } bool StructSchema::isStreamResult() const { auto& streamRaw = _::rawSchema(); return raw->generic == &streamRaw || raw->generic->canCastTo == &streamRaw; } Type StructSchema::Field::getType() const { auto proto = getProto(); uint location = _::RawBrandedSchema::makeDepLocation(_::RawBrandedSchema::DepKind::FIELD, index); switch (proto.which()) { case schema::Field::SLOT: return parent.interpretType(proto.getSlot().getType(), location); case schema::Field::GROUP: return parent.getDependency(proto.getGroup().getTypeId(), location).asStruct(); } KJ_UNREACHABLE; } uint32_t StructSchema::Field::getDefaultValueSchemaOffset() const { return parent.getSchemaOffset(proto.getSlot().getDefaultValue()); } kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field) { return field.getProto().getName(); } // ------------------------------------------------------------------- EnumSchema::EnumerantList EnumSchema::getEnumerants() const { return EnumerantList(*this, getProto().getEnum().getEnumerants()); } kj::Maybe EnumSchema::findEnumerantByName(kj::StringPtr name) const { return findSchemaMemberByName(raw->generic, name, getEnumerants()); } EnumSchema::Enumerant EnumSchema::getEnumerantByName(kj::StringPtr name) const { KJ_IF_MAYBE(enumerant, findEnumerantByName(name)) { return *enumerant; } else { KJ_FAIL_REQUIRE("enum has no such enumerant", name); } } // ------------------------------------------------------------------- InterfaceSchema::MethodList InterfaceSchema::getMethods() const { return MethodList(*this, getProto().getInterface().getMethods()); } kj::Maybe InterfaceSchema::findMethodByName(kj::StringPtr name) const { uint counter = 0; return findMethodByName(name, counter); } static constexpr uint MAX_SUPERCLASSES = 64; kj::Maybe InterfaceSchema::findMethodByName( kj::StringPtr name, uint& counter) const { // Security: Don't let someone DOS us with a dynamic schema containing cyclic inheritance. KJ_REQUIRE(counter++ < MAX_SUPERCLASSES, "Cyclic or absurdly-large inheritance graph detected.") { return nullptr; } auto result = findSchemaMemberByName(raw->generic, name, getMethods()); if (result == nullptr) { // Search superclasses. // TODO(perf): This may be somewhat slow, and in the case of lots of diamond dependencies it // could get pathological. Arguably we should generate a flat list of transitive // superclasses to search and store it in the RawSchema. It's problematic, though, because // this means that a dynamically-loaded RawSchema cannot be correctly constructed until all // superclasses have been loaded, which imposes an ordering requirement on SchemaLoader or // requires updating subclasses whenever a new superclass is loaded. auto superclasses = getProto().getInterface().getSuperclasses(); for (auto i: kj::indices(superclasses)) { auto superclass = superclasses[i]; uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::SUPERCLASS, i); result = getDependency(superclass.getId(), location) .asInterface().findMethodByName(name, counter); if (result != nullptr) { break; } } } return result; } InterfaceSchema::Method InterfaceSchema::getMethodByName(kj::StringPtr name) const { KJ_IF_MAYBE(method, findMethodByName(name)) { return *method; } else { KJ_FAIL_REQUIRE("interface has no such method", name); } } InterfaceSchema::SuperclassList InterfaceSchema::getSuperclasses() const { return SuperclassList(*this, getProto().getInterface().getSuperclasses()); } bool InterfaceSchema::extends(InterfaceSchema other) const { if (other.raw->generic == &_::NULL_INTERFACE_SCHEMA) { // We consider all interfaces to extend the null schema. return true; } uint counter = 0; return extends(other, counter); } bool InterfaceSchema::extends(InterfaceSchema other, uint& counter) const { // Security: Don't let someone DOS us with a dynamic schema containing cyclic inheritance. KJ_REQUIRE(counter++ < MAX_SUPERCLASSES, "Cyclic or absurdly-large inheritance graph detected.") { return false; } if (other == *this) { return true; } // TODO(perf): This may be somewhat slow. See findMethodByName() for discussion. auto superclasses = getProto().getInterface().getSuperclasses(); for (auto i: kj::indices(superclasses)) { auto superclass = superclasses[i]; uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::SUPERCLASS, i); if (getDependency(superclass.getId(), location).asInterface().extends(other, counter)) { return true; } } return false; } kj::Maybe InterfaceSchema::findSuperclass(uint64_t typeId) const { if (typeId == _::NULL_INTERFACE_SCHEMA.id) { // We consider all interfaces to extend the null schema. return InterfaceSchema(); } uint counter = 0; return findSuperclass(typeId, counter); } kj::Maybe InterfaceSchema::findSuperclass(uint64_t typeId, uint& counter) const { // Security: Don't let someone DOS us with a dynamic schema containing cyclic inheritance. KJ_REQUIRE(counter++ < MAX_SUPERCLASSES, "Cyclic or absurdly-large inheritance graph detected.") { return nullptr; } if (typeId == raw->generic->id) { return *this; } // TODO(perf): This may be somewhat slow. See findMethodByName() for discussion. auto superclasses = getProto().getInterface().getSuperclasses(); for (auto i: kj::indices(superclasses)) { auto superclass = superclasses[i]; uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::SUPERCLASS, i); KJ_IF_MAYBE(result, getDependency(superclass.getId(), location).asInterface() .findSuperclass(typeId, counter)) { return *result; } } return nullptr; } StructSchema InterfaceSchema::Method::getParamType() const { auto proto = getProto(); uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::METHOD_PARAMS, ordinal); return parent.getDependency(proto.getParamStructType(), location).asStruct(); } StructSchema InterfaceSchema::Method::getResultType() const { auto proto = getProto(); uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::METHOD_RESULTS, ordinal); return parent.getDependency(proto.getResultStructType(), location).asStruct(); } InterfaceSchema InterfaceSchema::SuperclassList::operator[](uint index) const { auto superclass = list[index]; uint location = _::RawBrandedSchema::makeDepLocation( _::RawBrandedSchema::DepKind::SUPERCLASS, index); return parent.getDependency(superclass.getId(), location).asInterface(); } // ------------------------------------------------------------------- uint32_t ConstSchema::getValueSchemaOffset() const { return getSchemaOffset(getProto().getConst().getValue()); } Type ConstSchema::getType() const { return interpretType(getProto().getConst().getType(), _::RawBrandedSchema::makeDepLocation(_::RawBrandedSchema::DepKind::CONST_TYPE, 0)); } // ======================================================================================= ListSchema ListSchema::of(schema::Type::Which primitiveType) { switch (primitiveType) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: break; case schema::Type::STRUCT: case schema::Type::ENUM: case schema::Type::INTERFACE: case schema::Type::LIST: KJ_FAIL_REQUIRE("Must use one of the other ListSchema::of() overloads for complex types."); break; case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("List(AnyPointer) not supported."); break; } return ListSchema(primitiveType); } ListSchema ListSchema::of(schema::Type::Reader elementType, Schema context) { // This method is deprecated because it can only be implemented in terms of other deprecated // methods. Temporarily disable warnings for those other deprecated methods. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" switch (elementType.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: return of(elementType.which()); case schema::Type::STRUCT: return of(context.getDependency(elementType.getStruct().getTypeId()).asStruct()); case schema::Type::ENUM: return of(context.getDependency(elementType.getEnum().getTypeId()).asEnum()); case schema::Type::INTERFACE: return of(context.getDependency(elementType.getInterface().getTypeId()).asInterface()); case schema::Type::LIST: return of(of(elementType.getList().getElementType(), context)); case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("List(AnyPointer) not supported."); return ListSchema(); } // Unknown type is acceptable. return ListSchema(elementType.which()); #pragma GCC diagnostic pop } // ======================================================================================= StructSchema Type::asStruct() const { KJ_REQUIRE(isStruct(), "Tried to interpret a non-struct type as a struct.") { return StructSchema(); } KJ_ASSERT(schema != nullptr); return StructSchema(Schema(schema)); } EnumSchema Type::asEnum() const { KJ_REQUIRE(isEnum(), "Tried to interpret a non-enum type as an enum.") { return EnumSchema(); } KJ_ASSERT(schema != nullptr); return EnumSchema(Schema(schema)); } InterfaceSchema Type::asInterface() const { KJ_REQUIRE(isInterface(), "Tried to interpret a non-interface type as an interface.") { return InterfaceSchema(); } KJ_ASSERT(schema != nullptr); return InterfaceSchema(Schema(schema)); } ListSchema Type::asList() const { KJ_REQUIRE(isList(), "Type::asList(): Not a list.") { return ListSchema::of(schema::Type::VOID); } Type elementType = *this; --elementType.listDepth; return ListSchema::of(elementType); } kj::Maybe Type::getBrandParameter() const { KJ_REQUIRE(isAnyPointer(), "Type::getBrandParameter() can only be called on AnyPointer types."); if (scopeId == 0) { return nullptr; } else { return BrandParameter { scopeId, paramIndex }; } } kj::Maybe Type::getImplicitParameter() const { KJ_REQUIRE(isAnyPointer(), "Type::getImplicitParameter() can only be called on AnyPointer types."); if (isImplicitParam) { return ImplicitParameter { paramIndex }; } else { return nullptr; } } bool Type::operator==(const Type& other) const { if (baseType != other.baseType || listDepth != other.listDepth) { return false; } switch (baseType) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: return true; case schema::Type::STRUCT: case schema::Type::ENUM: case schema::Type::INTERFACE: return schema == other.schema; case schema::Type::LIST: KJ_UNREACHABLE; case schema::Type::ANY_POINTER: return scopeId == other.scopeId && isImplicitParam == other.isImplicitParam && // Trying to comply with strict aliasing rules. Hopefully the compiler realizes that // both branches compile to the same instructions and can optimize it away. (scopeId != 0 || isImplicitParam ? paramIndex == other.paramIndex : anyPointerKind == other.anyPointerKind); } KJ_UNREACHABLE; } uint Type::hashCode() const { switch (baseType) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: if (listDepth == 0) { // Make sure that hashCode(Type(baseType)) == hashCode(baseType), otherwise HashMap lookups // keyed by `Type` won't work when the caller passes `baseType` as the key. return kj::hashCode(baseType); } else { return kj::hashCode(baseType, listDepth); } case schema::Type::STRUCT: case schema::Type::ENUM: case schema::Type::INTERFACE: if (listDepth == 0) { // Make sure that hashCode(Type(schema)) == hashCode(schema), otherwise HashMap lookups // keyed by `Type` won't work when the caller passes `schema` as the key. return kj::hashCode(schema); } else { return kj::hashCode(schema, listDepth); } case schema::Type::LIST: KJ_UNREACHABLE; case schema::Type::ANY_POINTER: { // Trying to comply with strict aliasing rules. Hopefully the compiler realizes that // both branches compile to the same instructions and can optimize it away. uint16_t val = scopeId != 0 || isImplicitParam ? paramIndex : static_cast(anyPointerKind); return kj::hashCode(val, isImplicitParam, scopeId, listDepth); } } KJ_UNREACHABLE; } void Type::requireUsableAs(Type expected) const { KJ_REQUIRE(baseType == expected.baseType && listDepth == expected.listDepth, "This type is not compatible with the requested native type."); switch (baseType) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ANY_POINTER: break; case schema::Type::STRUCT: case schema::Type::ENUM: case schema::Type::INTERFACE: Schema(schema).requireUsableAs(expected.schema->generic); break; case schema::Type::LIST: KJ_UNREACHABLE; } } } // namespace capnp capnproto-c++-1.1.0/src/capnp/common-test.c++0000644000175000017500000000627314527152321021403 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "common.h" #include #include #include #include #if HAVE_CONFIG_H #include "config.h" #endif namespace capnp { namespace { TEST(Common, Version) { #ifdef VERSION auto expectedVersion = kj::str(CAPNP_VERSION_MAJOR, '.', CAPNP_VERSION_MINOR, '.', CAPNP_VERSION_MICRO); auto devVersion = kj::str(CAPNP_VERSION_MAJOR, '.', CAPNP_VERSION_MINOR, "-dev"); kj::StringPtr actualVersion = VERSION; KJ_ASSERT(actualVersion == expectedVersion || actualVersion.startsWith(kj::str(expectedVersion, '-')) || actualVersion.startsWith(kj::str(expectedVersion, '.')) || (actualVersion == devVersion && CAPNP_VERSION_MICRO == 0), expectedVersion, actualVersion); #endif } struct ExampleStruct { struct _capnpPrivate { struct IsStruct; }; }; struct ExampleInterface { struct _capnpPrivate { struct IsInterface; }; }; static_assert(_::Kind_::kind == Kind::STRUCT, "Kind SFINAE failed."); static_assert(_::Kind_::kind == Kind::INTERFACE, "Kind SFINAE failed."); // Test FromAnay<> template struct EqualTypes_ { static constexpr bool value = false; }; template struct EqualTypes_ { static constexpr bool value = true; }; template inline constexpr bool equalTypes() { return EqualTypes_::value; } using capnproto_test::capnp::test::TestAllTypes; using capnproto_test::capnp::test::TestInterface; static_assert(equalTypes, int>(), ""); static_assert(equalTypes, TestAllTypes>(), ""); static_assert(equalTypes, TestAllTypes>(), ""); #if !CAPNP_LITE static_assert(equalTypes, TestAllTypes>(), ""); static_assert(equalTypes, TestInterface>(), ""); static_assert(equalTypes>, TestInterface>(), ""); #endif } // namespace } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize-text.c++0000644000175000017500000001313214712011043022066 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Philip Quinn. // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "serialize-text.h" #include #include "pretty-print.h" #include "compiler/lexer.capnp.h" #include "compiler/lexer.h" #include "compiler/node-translator.h" #include "compiler/parser.h" namespace capnp { namespace { class ThrowingErrorReporter final: public capnp::compiler::ErrorReporter { // Throws all errors as assertion failures. public: ThrowingErrorReporter(kj::StringPtr input): input(input) {} void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { // Note: Line and column numbers are usually 1-based. uint line = 1; uint32_t lineStart = 0; for (auto i: kj::zeroTo(startByte)) { if (input[i] == '\n') { ++line; lineStart = i; // Omit +1 so that column is 1-based. } } kj::throwRecoverableException(kj::Exception( kj::Exception::Type::FAILED, "(capnp text input)", line, kj::str(startByte - lineStart, "-", endByte - lineStart, ": ", message) )); } bool hadErrors() override { return false; } private: kj::StringPtr input; }; class ExternalResolver final: public capnp::compiler::ValueTranslator::Resolver { // Throws all external resolution requests as assertion failures. public: kj::Maybe resolveConstant(capnp::compiler::Expression::Reader name) override { KJ_FAIL_REQUIRE("External constants not allowed."); } kj::Maybe> readEmbed(capnp::compiler::LocatedText::Reader filename) override { KJ_FAIL_REQUIRE("External embeds not allowed."); } }; template void lexAndParseExpression(kj::StringPtr input, Function f) { // Parses a single expression from the input and calls `f(expression)`. ThrowingErrorReporter errorReporter(input); capnp::MallocMessageBuilder tokenArena; auto lexedTokens = tokenArena.initRoot(); capnp::compiler::lex(input, lexedTokens, errorReporter); capnp::compiler::CapnpParser parser(tokenArena.getOrphanage(), errorReporter); auto tokens = lexedTokens.asReader().getTokens(); capnp::compiler::CapnpParser::ParserInput parserInput(tokens.begin(), tokens.end()); if (parserInput.getPosition() != tokens.end()) { KJ_IF_MAYBE(expression, parser.getParsers().expression(parserInput)) { // The input is expected to contain a *single* message. KJ_REQUIRE(parserInput.getPosition() == tokens.end(), "Extra tokens in input."); f(expression->getReader()); } else { auto best = parserInput.getBest(); if (best == tokens.end()) { KJ_FAIL_REQUIRE("Premature end of input."); } else { errorReporter.addErrorOn(*best, "Parse error"); } } } else { KJ_FAIL_REQUIRE("Failed to read input."); } } } // namespace TextCodec::TextCodec() : prettyPrint(false) {} TextCodec::~TextCodec() noexcept(true) {} void TextCodec::setPrettyPrint(bool enabled) { prettyPrint = enabled; } kj::String TextCodec::encode(DynamicValue::Reader value) const { if (!prettyPrint) { return kj::str(value); } else { if (value.getType() == DynamicValue::Type::STRUCT) { return capnp::prettyPrint(value.as()).flatten(); } else if (value.getType() == DynamicValue::Type::LIST) { return capnp::prettyPrint(value.as()).flatten(); } else { return kj::str(value); } } } void TextCodec::decode(kj::StringPtr input, DynamicStruct::Builder output) const { lexAndParseExpression(input, [&](compiler::Expression::Reader expression) { KJ_REQUIRE(expression.isTuple(), "Input does not contain a struct.") { return; } ThrowingErrorReporter errorReporter(input); ExternalResolver nullResolver; Orphanage orphanage = Orphanage::getForMessageContaining(output); compiler::ValueTranslator translator(nullResolver, errorReporter, orphanage); translator.fillStructValue(output, expression.getTuple()); }); } Orphan TextCodec::decode(kj::StringPtr input, Type type, Orphanage orphanage) const { Orphan output; lexAndParseExpression(input, [&](compiler::Expression::Reader expression) { ThrowingErrorReporter errorReporter(input); ExternalResolver nullResolver; compiler::ValueTranslator translator(nullResolver, errorReporter, orphanage); KJ_IF_MAYBE(value, translator.compileValue(expression, type)) { output = *kj::mv(value); } else { // An error should have already been given to the errorReporter. } }); return output; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/fuzz-test.c++0000644000175000017500000002206614527152321021107 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include "message.h" #include "serialize.h" #include #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { bool skipFuzzTest() { if (getenv("CAPNP_SKIP_FUZZ_TEST") != nullptr) { KJ_LOG(WARNING, "Skipping test because CAPNP_SKIP_FUZZ_TEST is set in environment."); return true; } else { return false; } } class DisableStackTraces: public kj::ExceptionCallback { // This test generates a lot of exceptions. Performing a backtrace on each one can be slow, // especially on Windows (where it is very, very slow). So, disable them. public: StackTraceMode stackTraceMode() override { return StackTraceMode::NONE; } }; uint64_t traverse(AnyPointer::Reader reader); uint64_t traverse(AnyStruct::Reader reader); uint64_t traverse(AnyList::Reader reader); template uint64_t traverseList(ListType list) { // Traverse in reverse order in order to trigger segfaults before exceptions if we go // out-of-bounds. uint64_t result = 0; for (size_t i = list.size(); i != 0; i--) { result += traverse(list[i-1]); } return result; } uint64_t traverse(AnyStruct::Reader reader) { uint64_t result = 0; for (byte b: reader.getDataSection()) { result += b; } result += traverseList(reader.getPointerSection()); return result; } uint64_t traverse(AnyList::Reader reader) { uint64_t result = 0; switch (reader.getElementSize()) { case ElementSize::VOID: break; case ElementSize::BIT: for (auto e: reader.as>()) result += e; break; case ElementSize::BYTE: for (auto e: reader.as>()) result += e; break; case ElementSize::TWO_BYTES: for (auto e: reader.as>()) result += e; break; case ElementSize::FOUR_BYTES: for (auto e: reader.as>()) result += e; break; case ElementSize::EIGHT_BYTES: for (auto e: reader.as>()) result += e; break; case ElementSize::POINTER: traverseList(reader.as>()); break; case ElementSize::INLINE_COMPOSITE: traverseList(reader.as>()); break; } return result; } uint64_t traverse(AnyPointer::Reader reader) { if (reader.isStruct()) { return traverse(reader.getAs()); } else if (reader.isList()) { return traverse(reader.getAs()); } else { return 0; } } template void traverseCatchingExceptions(kj::ArrayPtr data) { // Try traversing through Checker. kj::runCatchingExceptions([&]() { FlatArrayMessageReader reader(data); KJ_ASSERT(Checker::check(reader) != 0) { break; } }); // Try traversing through AnyPointer. kj::runCatchingExceptions([&]() { FlatArrayMessageReader reader(data); KJ_ASSERT(traverse(reader.getRoot()) != 0) { break; } }); // Try counting the size.. kj::runCatchingExceptions([&]() { FlatArrayMessageReader reader(data); KJ_ASSERT(reader.getRoot().targetSize().wordCount != 0) { break; } }); // Try copying into a builder, and if that works, traversing it with Checker. static word buffer[8192]; kj::runCatchingExceptions([&]() { FlatArrayMessageReader reader(data); MallocMessageBuilder copyBuilder(buffer); copyBuilder.setRoot(reader.getRoot()); KJ_ASSERT(Checker::check(copyBuilder) != 0) { break; } }); } template void fuzz(kj::ArrayPtr data, uint flipCount, uint startAt, uint endAt) { if (flipCount == 0) { traverseCatchingExceptions(data); } else { for (uint i = startAt; i < endAt; i++) { byte bit = 1u << (i % 8); byte old = data.asBytes()[i / 8]; data.asBytes()[i / 8] |= bit; fuzz(data, flipCount - 1, i + 1, endAt); data.asBytes()[i / 8] &= ~bit; fuzz(data, flipCount - 1, i + 1, endAt); data.asBytes()[i / 8] = bit; fuzz(data, flipCount - 1, i + 1, endAt); data.asBytes()[i / 8] = old; } } } struct StructChecker { template static uint check(ReaderOrBuilder& message) { uint result = 0; for (auto c: message.template getRoot().getTextField()) { result += c; } return result; } }; KJ_TEST("fuzz-test struct pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder; builder.getRoot().setTextField("foo"); KJ_ASSERT(builder.getSegmentsForOutput().size() == 1); fuzz(messageToFlatArray(builder), 2, 64, 192); } struct ListChecker { template static uint check(ReaderOrBuilder& message) { uint result = 0; for (auto e: message.template getRoot>()) { result += e; } return result; } }; KJ_TEST("fuzz-test list pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder; auto list = builder.getRoot().initAs>(2); list.set(0, 12345); list.set(1, 67890); fuzz(messageToFlatArray(builder), 2, 64, 192); } struct StructListChecker { template static uint check(ReaderOrBuilder& message) { uint result = 0; auto l = message.template getRoot>(); for (size_t i = l.size(); i > 0; i--) { for (auto c: l[i-1].getTextField()) { result += c; } } return result; } }; KJ_TEST("fuzz-test struct list pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder; auto list = builder.getRoot().initAs>(2); list[0].setTextField("foo"); list[1].setTextField("bar"); KJ_ASSERT(builder.getSegmentsForOutput().size() == 1); fuzz(messageToFlatArray(builder), 2, 64, 192); } struct TextChecker { template static uint check(ReaderOrBuilder& message) { uint result = 0; for (auto c: message.template getRoot()) { result += c; } return result; } }; KJ_TEST("fuzz-test text pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder; builder.template getRoot().setAs("foo"); fuzz(messageToFlatArray(builder), 2, 64, 192); } KJ_TEST("fuzz-test far pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder(1, AllocationStrategy::FIXED_SIZE); initTestMessage(builder.getRoot()); uint segmentCount = builder.getSegmentsForOutput().size(); uint tableSize = segmentCount / 2 + 1; // Fuzz the root far pointer plus its landing pad, which should be in the next word. fuzz(messageToFlatArray(builder), 2, tableSize * 64, tableSize * 64 + 128); } KJ_TEST("fuzz-test double-far pointer") { if (skipFuzzTest()) return; DisableStackTraces disableStackTraces; MallocMessageBuilder builder(1, AllocationStrategy::FIXED_SIZE); // Carefully arrange for a double-far pointer to be created. auto root = builder.getRoot(); root.adopt(builder.getOrphanage().newOrphanCopy(Text::Reader("foo"))); // Verify that did what we expected. KJ_ASSERT(builder.getSegmentsForOutput().size() == 3); KJ_ASSERT(builder.getSegmentsForOutput()[0].size() == 1); // root pointer KJ_ASSERT(builder.getSegmentsForOutput()[1].size() == 1); // "foo" KJ_ASSERT(builder.getSegmentsForOutput()[2].size() == 2); // double-far landing pad // Fuzz the root far pointer. fuzz(messageToFlatArray(builder), 2, 64, 128); // Fuzz the landing pad. fuzz(messageToFlatArray(builder), 2, 192, 320); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc-twoparty-test.c++0000644000175000017500000012721214712011043022552 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif // Includes just for need SOL_SOCKET and SO_SNDBUF #if _WIN32 #include #endif #include "rpc-twoparty.h" #include "test-util.h" #include #include #include #include #include #if _WIN32 #include #include #include #else #include #endif // TODO(cleanup): Auto-generate stringification functions for union discriminants. namespace capnp { namespace rpc { inline kj::String KJ_STRINGIFY(Message::Which which) { return kj::str(static_cast(which)); } } // namespace rpc } // namespace capnp namespace capnp { namespace _ { namespace { class TestRestorer final: public SturdyRefRestorer { public: TestRestorer(int& callCount, int& handleCount) : callCount(callCount), handleCount(handleCount) {} Capability::Client restore(test::TestSturdyRefObjectId::Reader objectId) override { switch (objectId.getTag()) { case test::TestSturdyRefObjectId::Tag::TEST_INTERFACE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_EXTENDS: return Capability::Client(newBrokenCap("No TestExtends implemented.")); case test::TestSturdyRefObjectId::Tag::TEST_PIPELINE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLEE: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_TAIL_CALLER: return kj::heap(callCount); case test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF: return kj::heap(callCount, handleCount); } KJ_UNREACHABLE; } private: int& callCount; int& handleCount; }; class TestMonotonicClock final: public kj::MonotonicClock { public: kj::TimePoint now() const override { return time; } void reset() { time = kj::systemCoarseMonotonicClock().now(); } void increment(kj::Duration d) { time += d; } private: kj::TimePoint time = kj::systemCoarseMonotonicClock().now(); }; kj::AsyncIoProvider::PipeThread runServer(kj::AsyncIoProvider& ioProvider, int& callCount, int& handleCount) { return ioProvider.newPipeThread( [&callCount, &handleCount]( kj::AsyncIoProvider& ioProvider, kj::AsyncIoStream& stream, kj::WaitScope& waitScope) { TwoPartyVatNetwork network(stream, rpc::twoparty::Side::SERVER); TestRestorer restorer(callCount, handleCount); auto server = makeRpcServer(network, restorer); network.onDisconnect().wait(waitScope); }); } Capability::Client getPersistentCap(RpcSystem& client, rpc::twoparty::Side side, test::TestSturdyRefObjectId::Tag tag) { // Create the VatId. MallocMessageBuilder hostIdMessage(8); auto hostId = hostIdMessage.initRoot(); hostId.setSide(side); // Create the SturdyRefObjectId. MallocMessageBuilder objectIdMessage(8); objectIdMessage.initRoot().setTag(tag); // Connect to the remote capability. return client.restore(hostId, objectIdMessage.getRoot()); } TEST(TwoPartyNetwork, Basic) { auto ioContext = kj::setupAsyncIo(); TestMonotonicClock clock; int callCount = 0; int handleCount = 0; auto serverThread = runServer(*ioContext.provider, callCount, handleCount); TwoPartyVatNetwork network(*serverThread.pipe, rpc::twoparty::Side::CLIENT, capnp::ReaderOptions(), clock); auto rpcClient = makeRpcClient(network); KJ_EXPECT(network.getCurrentQueueCount() == 0); KJ_EXPECT(network.getCurrentQueueSize() == 0); KJ_EXPECT(network.getOutgoingMessageWaitTime() == 0 * kj::SECONDS); // Request the particular capability from the server. auto client = getPersistentCap(rpcClient, rpc::twoparty::Side::SERVER, test::TestSturdyRefObjectId::Tag::TEST_INTERFACE).castAs(); clock.increment(1 * kj::SECONDS); KJ_EXPECT(network.getCurrentQueueCount() == 1); KJ_EXPECT(network.getCurrentQueueSize() % sizeof(word) == 0); KJ_EXPECT(network.getCurrentQueueSize() > 0); KJ_EXPECT(network.getOutgoingMessageWaitTime() == 1 * kj::SECONDS); size_t oldSize = network.getCurrentQueueSize(); // Use the capability. auto request1 = client.fooRequest(); request1.setI(123); request1.setJ(true); auto promise1 = request1.send(); KJ_EXPECT(network.getCurrentQueueCount() == 2); KJ_EXPECT(network.getCurrentQueueSize() % sizeof(word) == 0); KJ_EXPECT(network.getCurrentQueueSize() > oldSize); KJ_EXPECT(network.getOutgoingMessageWaitTime() == 1 * kj::SECONDS); oldSize = network.getCurrentQueueSize(); auto request2 = client.bazRequest(); initTestMessage(request2.initS()); auto promise2 = request2.send(); KJ_EXPECT(network.getCurrentQueueCount() == 3); KJ_EXPECT(network.getCurrentQueueSize() % sizeof(word) == 0); KJ_EXPECT(network.getCurrentQueueSize() > oldSize); oldSize = network.getCurrentQueueSize(); clock.increment(1 * kj::SECONDS); bool barFailed = false; auto request3 = client.barRequest(); auto promise3 = request3.send().then( [](Response&& response) { ADD_FAILURE() << "Expected bar() call to fail."; }, [&](kj::Exception&& e) { barFailed = true; }); EXPECT_EQ(0, callCount); KJ_EXPECT(network.getCurrentQueueCount() == 4); KJ_EXPECT(network.getCurrentQueueSize() % sizeof(word) == 0); KJ_EXPECT(network.getCurrentQueueSize() > oldSize); // Oldest message is now 2 seconds old KJ_EXPECT(network.getOutgoingMessageWaitTime() == 2 * kj::SECONDS); oldSize = network.getCurrentQueueSize(); auto response1 = promise1.wait(ioContext.waitScope); EXPECT_EQ("foo", response1.getX()); auto response2 = promise2.wait(ioContext.waitScope); promise3.wait(ioContext.waitScope); EXPECT_EQ(2, callCount); EXPECT_TRUE(barFailed); // There's still a `Finish` message queued. KJ_EXPECT(network.getCurrentQueueCount() > 0); KJ_EXPECT(network.getCurrentQueueSize() > 0); // Oldest message was sent, next oldest should be 0 seconds old since we haven't incremented // the clock yet. KJ_EXPECT(network.getOutgoingMessageWaitTime() == 0 * kj::SECONDS); // Let any I/O finish. kj::Promise(kj::NEVER_DONE).poll(ioContext.waitScope); // Now nothing is queued. KJ_EXPECT(network.getCurrentQueueCount() == 0); KJ_EXPECT(network.getCurrentQueueSize() == 0); // Ensure that sending a message after not sending one for some time // doesn't return incorrect waitTime statistics. clock.increment(10 * kj::SECONDS); auto request4 = client.fooRequest(); request4.setI(123); request4.setJ(true); auto promise4 = request4.send(); KJ_EXPECT(network.getCurrentQueueCount() == 1); KJ_EXPECT(network.getOutgoingMessageWaitTime() == 0 * kj::SECONDS); } TEST(TwoPartyNetwork, Pipelining) { auto ioContext = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; int reverseCallCount = 0; // Calls back from server to client. auto serverThread = runServer(*ioContext.provider, callCount, handleCount); TwoPartyVatNetwork network(*serverThread.pipe, rpc::twoparty::Side::CLIENT); auto rpcClient = makeRpcClient(network); bool disconnected = false; kj::Promise disconnectPromise = network.onDisconnect().then([&]() { disconnected = true; }); { // Request the particular capability from the server. auto client = getPersistentCap(rpcClient, rpc::twoparty::Side::SERVER, test::TestSturdyRefObjectId::Tag::TEST_PIPELINE).castAs(); { // Use the capability. auto request = client.getCapRequest(); request.setN(234); request.setInCap(kj::heap(reverseCallCount)); auto promise = request.send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap() .castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, callCount); EXPECT_EQ(0, reverseCallCount); auto response = pipelinePromise.wait(ioContext.waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(ioContext.waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, reverseCallCount); } EXPECT_FALSE(disconnected); // What if we disconnect? // TODO(cleanup): This is kind of cheating, we are shutting down the underlying socket to // simulate a disconnect, but it's weird to pull the rug out from under our VatNetwork like // this and it causes a bit of a race between write failures and read failures. This part of // the test should maybe be restructured. serverThread.pipe->shutdownWrite(); // The other side should also disconnect. disconnectPromise.wait(ioContext.waitScope); { // Use the now-broken capability. auto request = client.getCapRequest(); request.setN(234); request.setInCap(kj::heap(reverseCallCount)); auto promise = request.send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap() .castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); pipelinePromise.then([](auto) { KJ_FAIL_EXPECT("should have thrown"); }, [](kj::Exception&& e) { KJ_EXPECT(e.getType() == kj::Exception::Type::DISCONNECTED); // I wish we could test stack traces somehow... oh well. }).wait(ioContext.waitScope); pipelinePromise2.then([](auto) { KJ_FAIL_EXPECT("should have thrown"); }, [](kj::Exception&& e) { KJ_EXPECT(e.getType() == kj::Exception::Type::DISCONNECTED); // I wish we could test stack traces somehow... oh well. }).wait(ioContext.waitScope); EXPECT_EQ(3, callCount); EXPECT_EQ(1, reverseCallCount); } } } TEST(TwoPartyNetwork, Release) { auto ioContext = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; auto serverThread = runServer(*ioContext.provider, callCount, handleCount); TwoPartyVatNetwork network(*serverThread.pipe, rpc::twoparty::Side::CLIENT); auto rpcClient = makeRpcClient(network); // Request the particular capability from the server. auto client = getPersistentCap(rpcClient, rpc::twoparty::Side::SERVER, test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF).castAs(); auto handle1 = client.getHandleRequest().send().wait(ioContext.waitScope).getHandle(); auto promise = client.getHandleRequest().send(); auto handle2 = promise.wait(ioContext.waitScope).getHandle(); EXPECT_EQ(2, handleCount); handle1 = nullptr; // There once was a bug where the last outgoing message (and any capabilities attached) would // not get cleaned up (until a new message was sent). This appeared to be a bug in Release, // because if a client received a message and then released a capability from it but then did // not make any further calls, then the capability would not be released because the message // introducing it remained the last server -> client message (because a "Release" message has // no reply). Here we are explicitly trying to catch this bug. This proves tricky, because when // we drop a reference on the client side, there's no particular way to wait for the release // message to reach the server except to make a subsequent call and wait for the return -- but // that would mask the bug. So, we wait spin waiting for handleCount to change. uint maxSpins = 1000; while (handleCount > 1) { ioContext.provider->getTimer().afterDelay(10 * kj::MILLISECONDS).wait(ioContext.waitScope); KJ_ASSERT(--maxSpins > 0); } EXPECT_EQ(1, handleCount); handle2 = nullptr; ioContext.provider->getTimer().afterDelay(10 * kj::MILLISECONDS).wait(ioContext.waitScope); EXPECT_EQ(1, handleCount); promise = nullptr; while (handleCount > 0) { ioContext.provider->getTimer().afterDelay(10 * kj::MILLISECONDS).wait(ioContext.waitScope); KJ_ASSERT(--maxSpins > 0); } EXPECT_EQ(0, handleCount); } TEST(TwoPartyNetwork, Abort) { // Verify that aborts are received. auto ioContext = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; auto serverThread = runServer(*ioContext.provider, callCount, handleCount); TwoPartyVatNetwork network(*serverThread.pipe, rpc::twoparty::Side::CLIENT); MallocMessageBuilder refMessage(128); auto hostId = refMessage.initRoot(); hostId.setSide(rpc::twoparty::Side::SERVER); auto conn = KJ_ASSERT_NONNULL(network.connect(hostId)); { // Send an invalid message (Return to non-existent question). auto msg = conn->newOutgoingMessage(128); auto body = msg->getBody().initAs().initReturn(); body.setAnswerId(1234); body.setCanceled(); msg->send(); } { auto reply = KJ_ASSERT_NONNULL(conn->receiveIncomingMessage().wait(ioContext.waitScope)); EXPECT_EQ(rpc::Message::ABORT, reply->getBody().getAs().which()); } EXPECT_TRUE(conn->receiveIncomingMessage().wait(ioContext.waitScope) == nullptr); } TEST(TwoPartyNetwork, ConvenienceClasses) { auto ioContext = kj::setupAsyncIo(); int callCount = 0; TwoPartyServer server(kj::heap(callCount)); auto address = ioContext.provider->getNetwork() .parseAddress("127.0.0.1").wait(ioContext.waitScope); auto listener = address->listen(); auto listenPromise = server.listen(*listener); address = ioContext.provider->getNetwork() .parseAddress("127.0.0.1", listener->getPort()).wait(ioContext.waitScope); auto connection = address->connect().wait(ioContext.waitScope); TwoPartyClient client(*connection); auto cap = client.bootstrap().castAs(); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); EXPECT_EQ(0, callCount); auto response = request.send().wait(ioContext.waitScope); EXPECT_EQ("foo", response.getX()); EXPECT_EQ(1, callCount); } TEST(TwoPartyNetwork, HugeMessage) { auto ioContext = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; auto serverThread = runServer(*ioContext.provider, callCount, handleCount); TwoPartyVatNetwork network(*serverThread.pipe, rpc::twoparty::Side::CLIENT); auto rpcClient = makeRpcClient(network); auto client = getPersistentCap(rpcClient, rpc::twoparty::Side::SERVER, test::TestSturdyRefObjectId::Tag::TEST_MORE_STUFF).castAs(); // Oversized request fails. { auto req = client.methodWithDefaultsRequest(); req.initA(100000000); // 100 MB KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("larger than our single-message size limit", req.send().ignoreResult().wait(ioContext.waitScope)); } // Oversized response fails. KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("larger than our single-message size limit", client.getEnormousStringRequest().send().ignoreResult().wait(ioContext.waitScope)); // Connection is still up. { auto req = client.getCallSequenceRequest(); req.setExpected(0); KJ_EXPECT(req.send().wait(ioContext.waitScope).getN() == 0); } } class TestAuthenticatedBootstrapImpl final : public test::TestAuthenticatedBootstrap::Server { public: TestAuthenticatedBootstrapImpl(rpc::twoparty::VatId::Reader clientId) { this->clientId.setRoot(clientId); } protected: kj::Promise getCallerId(GetCallerIdContext context) override { context.getResults().setCaller(clientId.getRoot()); return kj::READY_NOW; } private: MallocMessageBuilder clientId; }; class TestBootstrapFactory: public BootstrapFactory { public: Capability::Client createFor(rpc::twoparty::VatId::Reader clientId) { called = true; EXPECT_EQ(rpc::twoparty::Side::CLIENT, clientId.getSide()); return kj::heap(clientId); } bool called = false; }; kj::AsyncIoProvider::PipeThread runAuthenticatingServer( kj::AsyncIoProvider& ioProvider, BootstrapFactory& bootstrapFactory) { return ioProvider.newPipeThread([&bootstrapFactory]( kj::AsyncIoProvider& ioProvider, kj::AsyncIoStream& stream, kj::WaitScope& waitScope) { TwoPartyVatNetwork network(stream, rpc::twoparty::Side::SERVER); auto server = makeRpcServer(network, bootstrapFactory); network.onDisconnect().wait(waitScope); }); } TEST(TwoPartyNetwork, BootstrapFactory) { auto ioContext = kj::setupAsyncIo(); TestBootstrapFactory bootstrapFactory; auto serverThread = runAuthenticatingServer(*ioContext.provider, bootstrapFactory); TwoPartyClient client(*serverThread.pipe); auto resp = client.bootstrap().castAs>() .getCallerIdRequest().send().wait(ioContext.waitScope); EXPECT_EQ(rpc::twoparty::Side::CLIENT, resp.getCaller().getSide()); EXPECT_TRUE(bootstrapFactory.called); } // ======================================================================================= #if !_WIN32 && !__CYGWIN__ // Windows and Cygwin don't support SCM_RIGHTS. KJ_TEST("send FD over RPC") { auto io = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; TwoPartyServer server(kj::heap(callCount, handleCount)); auto pipe = io.provider->newCapabilityPipe(); server.accept(kj::mv(pipe.ends[0]), 2); TwoPartyClient client(*pipe.ends[1], 2); auto cap = client.bootstrap().castAs(); int pipeFds[2]; KJ_SYSCALL(kj::miniposix::pipe(pipeFds)); kj::AutoCloseFd in1(pipeFds[0]); kj::AutoCloseFd out1(pipeFds[1]); KJ_SYSCALL(kj::miniposix::pipe(pipeFds)); kj::AutoCloseFd in2(pipeFds[0]); kj::AutoCloseFd out2(pipeFds[1]); capnp::RemotePromise promise = nullptr; { auto req = cap.writeToFdRequest(); // Order reversal intentional, just trying to mix things up. req.setFdCap1(kj::heap(kj::mv(out2))); req.setFdCap2(kj::heap(kj::mv(out1))); promise = req.send(); } int in3 = KJ_ASSERT_NONNULL(promise.getFdCap3().getFd().wait(io.waitScope)); KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in3))->readAllText().wait(io.waitScope) == "baz"); { auto promise2 = kj::mv(promise); // make sure the PipelineHook also goes out of scope auto response = promise2.wait(io.waitScope); KJ_EXPECT(response.getSecondFdPresent()); } KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in1))->readAllText().wait(io.waitScope) == "bar"); KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in2))->readAllText().wait(io.waitScope) == "foo"); } KJ_TEST("FD per message limit") { auto io = kj::setupAsyncIo(); int callCount = 0; int handleCount = 0; TwoPartyServer server(kj::heap(callCount, handleCount)); auto pipe = io.provider->newCapabilityPipe(); server.accept(kj::mv(pipe.ends[0]), 1); TwoPartyClient client(*pipe.ends[1], 1); auto cap = client.bootstrap().castAs(); int pipeFds[2]; KJ_SYSCALL(kj::miniposix::pipe(pipeFds)); kj::AutoCloseFd in1(pipeFds[0]); kj::AutoCloseFd out1(pipeFds[1]); KJ_SYSCALL(kj::miniposix::pipe(pipeFds)); kj::AutoCloseFd in2(pipeFds[0]); kj::AutoCloseFd out2(pipeFds[1]); capnp::RemotePromise promise = nullptr; { auto req = cap.writeToFdRequest(); // Order reversal intentional, just trying to mix things up. req.setFdCap1(kj::heap(kj::mv(out2))); req.setFdCap2(kj::heap(kj::mv(out1))); promise = req.send(); } int in3 = KJ_ASSERT_NONNULL(promise.getFdCap3().getFd().wait(io.waitScope)); KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in3))->readAllText().wait(io.waitScope) == "baz"); { auto promise2 = kj::mv(promise); // make sure the PipelineHook also goes out of scope auto response = promise2.wait(io.waitScope); KJ_EXPECT(!response.getSecondFdPresent()); } KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in1))->readAllText().wait(io.waitScope) == ""); KJ_EXPECT(io.lowLevelProvider->wrapInputFd(kj::mv(in2))->readAllText().wait(io.waitScope) == "foo"); } #endif // !_WIN32 && !__CYGWIN__ // ======================================================================================= class MockSndbufStream final: public kj::AsyncIoStream { public: MockSndbufStream(kj::Own inner, size_t& window, size_t& written) : inner(kj::mv(inner)), window(window), written(written) {} kj::Promise read(void* buffer, size_t minBytes, size_t maxBytes) override { return inner->read(buffer, minBytes, maxBytes); } kj::Promise tryRead(void* buffer, size_t minBytes, size_t maxBytes) override { return inner->tryRead(buffer, minBytes, maxBytes); } kj::Maybe tryGetLength() override { return inner->tryGetLength(); } kj::Promise pumpTo(AsyncOutputStream& output, uint64_t amount) override { return inner->pumpTo(output, amount); } kj::Promise write(const void* buffer, size_t size) override { written += size; return inner->write(buffer, size); } kj::Promise write(kj::ArrayPtr> pieces) override { for (auto& piece: pieces) written += piece.size(); return inner->write(pieces); } kj::Maybe> tryPumpFrom( kj::AsyncInputStream& input, uint64_t amount) override { return inner->tryPumpFrom(input, amount); } kj::Promise whenWriteDisconnected() override { return inner->whenWriteDisconnected(); } void shutdownWrite() override { return inner->shutdownWrite(); } void abortRead() override { return inner->abortRead(); } void getsockopt(int level, int option, void* value, uint* length) override { if (level == SOL_SOCKET && option == SO_SNDBUF) { KJ_ASSERT(*length == sizeof(int)); *reinterpret_cast(value) = window; } else { KJ_UNIMPLEMENTED("not implemented for test", level, option); } } private: kj::Own inner; size_t& window; size_t& written; }; KJ_TEST("Streaming over RPC") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); size_t window = 1024; size_t clientWritten = 0; size_t serverWritten = 0; pipe.ends[0] = kj::heap(kj::mv(pipe.ends[0]), window, clientWritten); pipe.ends[1] = kj::heap(kj::mv(pipe.ends[1]), window, serverWritten); auto ownServer = kj::heap(); auto& server = *ownServer; test::TestStreaming::Client serverCap(kj::mv(ownServer)); TwoPartyClient tpClient(*pipe.ends[0]); TwoPartyClient tpServer(*pipe.ends[1], serverCap, rpc::twoparty::Side::SERVER); auto cap = tpClient.bootstrap().castAs(); // Send stream requests until we can't anymore. kj::Promise promise = kj::READY_NOW; uint count = 0; while (promise.poll(waitScope)) { promise.wait(waitScope); auto req = cap.doStreamIRequest(); req.setI(++count); promise = req.send(); } // We should have sent... several. KJ_EXPECT(count > 5); // Now, cause calls to finish server-side one-at-a-time and check that this causes the client // side to be willing to send more. uint countReceived = 0; for (uint i = 0; i < 50; i++) { KJ_EXPECT(server.iSum == ++countReceived); server.iSum = 0; KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_ASSERT(promise.poll(waitScope)); promise.wait(waitScope); auto req = cap.doStreamIRequest(); req.setI(++count); promise = req.send(); if (promise.poll(waitScope)) { // We'll see a couple of instances where completing one request frees up space to make two // more. This is because the first few requests we made are a little bit larger than the // rest due to being pipelined on the bootstrap. Once the bootstrap resolves, the request // size gets smaller. promise.wait(waitScope); req = cap.doStreamIRequest(); req.setI(++count); promise = req.send(); // We definitely shouldn't have freed up stream space for more than two additional requests! KJ_ASSERT(!promise.poll(waitScope)); } } } KJ_TEST("Streaming over a chain of local and remote RPC calls") { // This test verifies that a local RPC call that eventually resolves to a remote RPC call will // still support streaming calls over the remote connection. kj::EventLoop loop; kj::WaitScope waitScope(loop); // Set up a local server that will eventually delegate requests to a remote server. auto localPaf = kj::newPromiseAndFulfiller(); test::TestStreaming::Client promisedClient(kj::mv(localPaf.promise)); uint count = 0; auto req = promisedClient.doStreamIRequest(); req.setI(++count); auto promise = req.send(); // Expect streaming request to be blocked on promised client. KJ_EXPECT(!promise.poll(waitScope)); // Set up a remote server with a flow control window for streaming. auto pipe = kj::newTwoWayPipe(); size_t window = 1024; size_t clientWritten = 0; size_t serverWritten = 0; pipe.ends[0] = kj::heap(kj::mv(pipe.ends[0]), window, clientWritten); pipe.ends[1] = kj::heap(kj::mv(pipe.ends[1]), window, serverWritten); auto remotePaf = kj::newPromiseAndFulfiller(); test::TestStreaming::Client serverCap(kj::mv(remotePaf.promise)); TwoPartyClient tpClient(*pipe.ends[0]); TwoPartyClient tpServer(*pipe.ends[1], kj::mv(serverCap), rpc::twoparty::Side::SERVER); auto clientCap = tpClient.bootstrap().castAs(); // Expect streaming request to be unblocked by fulfilling promised client with remote server. localPaf.fulfiller->fulfill(kj::mv(clientCap)); KJ_EXPECT(promise.poll(waitScope)); // Send stream requests until we can't anymore. while (promise.poll(waitScope)) { promise.wait(waitScope); auto req = promisedClient.doStreamIRequest(); req.setI(++count); promise = req.send(); KJ_ASSERT(count < 1000); } // Expect several stream requests to have fit in the flow control window. KJ_EXPECT(count > 5); auto finishReq = promisedClient.finishStreamRequest(); auto finishPromise = finishReq.send(); KJ_EXPECT(!finishPromise.poll(waitScope)); // Finish calls on server auto ownServer = kj::heap(); auto& server = *ownServer; remotePaf.fulfiller->fulfill(kj::mv(ownServer)); KJ_EXPECT(!promise.poll(waitScope)); uint countReceived = 0; for (uint i = 0; i < count; i++) { KJ_EXPECT(server.iSum == ++countReceived); server.iSum = 0; KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); if (i < count - 1) { KJ_EXPECT(!finishPromise.poll(waitScope)); } } KJ_EXPECT(finishPromise.poll(waitScope)); finishPromise.wait(waitScope); } KJ_TEST("Streaming over RPC then unwrap with CapabilitySet") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); CapabilityServerSet capSet; auto ownServer = kj::heap(); auto& server = *ownServer; auto serverCap = capSet.add(kj::mv(ownServer)); auto paf = kj::newPromiseAndFulfiller(); TwoPartyClient tpClient(*pipe.ends[0], serverCap); TwoPartyClient tpServer(*pipe.ends[1], kj::mv(paf.promise), rpc::twoparty::Side::SERVER); auto clientCap = tpClient.bootstrap().castAs(); // Send stream requests until we can't anymore. kj::Promise promise = kj::READY_NOW; uint count = 0; while (promise.poll(waitScope)) { promise.wait(waitScope); auto req = clientCap.doStreamIRequest(); req.setI(++count); promise = req.send(); } // We should have sent... several. KJ_EXPECT(count > 10); // Now try to unwrap. auto unwrapPromise = capSet.getLocalServer(clientCap); // It won't work yet, obviously, because we haven't resolved the promise. KJ_EXPECT(!unwrapPromise.poll(waitScope)); // So do that. paf.fulfiller->fulfill(tpServer.bootstrap().castAs()); clientCap.whenResolved().wait(waitScope); // But the unwrap still doesn't resolve because streaming requests are queued up. KJ_EXPECT(!unwrapPromise.poll(waitScope)); // OK, let's resolve a streaming request. KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); // All of our call promises have now completed from the client's perspective. promise.wait(waitScope); // But we still can't unwrap, because calls are queued server-side. KJ_EXPECT(!unwrapPromise.poll(waitScope)); // Let's even make one more call now. But this is actually a local call since the promise // resolved. { auto req = clientCap.doStreamIRequest(); req.setI(++count); promise = req.send(); } // Because it's a local call, it doesn't resolve early. The window is no longer in effect. KJ_EXPECT(!promise.poll(waitScope)); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(!promise.poll(waitScope)); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(!promise.poll(waitScope)); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(!promise.poll(waitScope)); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(!promise.poll(waitScope)); // Our unwrap promise is also still not resolved. KJ_EXPECT(!unwrapPromise.poll(waitScope)); // Close out stream calls until it does resolve! while (!unwrapPromise.poll(waitScope)) { KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); } // Now we can unwrap! KJ_EXPECT(&KJ_ASSERT_NONNULL(unwrapPromise.wait(waitScope)) == &server); // But our last stream call still isn't done. KJ_EXPECT(!promise.poll(waitScope)); // Finish it. KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); promise.wait(waitScope); } KJ_TEST("promise cap resolves between starting request and sending it") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); // Client exports TestCallOrderImpl as its bootstrap. TwoPartyClient client(*pipe.ends[0], kj::heap(), rpc::twoparty::Side::CLIENT); // Server exports a promise, which will later resolve to loop back to the capability the client // exported. auto paf = kj::newPromiseAndFulfiller(); TwoPartyClient server(*pipe.ends[1], kj::mv(paf.promise), rpc::twoparty::Side::SERVER); // Create a request but don't send it yet. auto cap = client.bootstrap().castAs(); auto req1 = cap.getCallSequenceRequest(); // Fulfill the promise now so that the server's bootstrap loops back to the client's bootstrap. paf.fulfiller->fulfill(server.bootstrap()); cap.whenResolved().wait(waitScope); // Send the request we created earlier, and also create and send a second request. auto promise1 = req1.send(); auto promise2 = cap.getCallSequenceRequest().send(); // They should arrive in order of send()s. auto n1 = promise1.wait(waitScope).getN(); KJ_EXPECT(n1 == 0, n1); auto n2 = promise2.wait(waitScope).getN(); KJ_EXPECT(n2 == 1, n2); } KJ_TEST("write error propagates to read error") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto frontPipe = kj::newTwoWayPipe(); auto backPipe = kj::newTwoWayPipe(); TwoPartyClient client(*frontPipe.ends[0]); int callCount; TwoPartyClient server(*backPipe.ends[1], kj::heap(callCount), rpc::twoparty::Side::SERVER); auto pumpUpTask = frontPipe.ends[1]->pumpTo(*backPipe.ends[0]); auto pumpDownTask = backPipe.ends[0]->pumpTo(*frontPipe.ends[1]); auto cap = client.bootstrap().castAs(); // Make sure the connections work. { auto req = cap.fooRequest(); req.setI(123); req.setJ(true); auto resp = req.send().wait(waitScope); EXPECT_EQ("foo", resp.getX()); } // Disconnect upstream task in such a way that future writes on the client will fail, but the // server doesn't notice the disconnect and so won't react. pumpUpTask = nullptr; frontPipe.ends[1]->abortRead(); // causes write() on ends[0] to fail in the future { auto req = cap.fooRequest(); req.setI(123); req.setJ(true); auto promise = req.send().then([](auto) { KJ_FAIL_EXPECT("expected exception"); }, [](kj::Exception&& e) { KJ_ASSERT(e.getDescription() == "abortRead() has been called"); }); KJ_ASSERT(promise.poll(waitScope)); promise.wait(waitScope); } } class TestStreamingCancellationBug final: public test::TestStreaming::Server { public: uint iSum = 0; kj::Maybe>> fulfiller; kj::Promise doStreamI(DoStreamIContext context) override { auto paf = kj::newPromiseAndFulfiller(); fulfiller = kj::mv(paf.fulfiller); return paf.promise.then([this,context]() mutable { // Don't count the sum until here so we actually detect if the call is canceled. iSum += context.getParams().getI(); }); } kj::Promise finishStream(FinishStreamContext context) override { auto results = context.getResults(); results.setTotalI(iSum); return kj::READY_NOW; } }; KJ_TEST("Streaming over RPC no premature cancellation when client dropped") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); auto ownServer = kj::heap(); auto& server = *ownServer; test::TestStreaming::Client serverCap = kj::mv(ownServer); TwoPartyClient tpClient(*pipe.ends[0]); TwoPartyClient tpServer(*pipe.ends[1], kj::mv(serverCap), rpc::twoparty::Side::SERVER); auto client = tpClient.bootstrap().castAs(); kj::Promise promise1 = nullptr, promise2 = nullptr; { auto req = client.doStreamIRequest(); req.setI(123); promise1 = req.send(); } { auto req = client.doStreamIRequest(); req.setI(456); promise2 = req.send(); } auto finishPromise = client.finishStreamRequest().send(); KJ_EXPECT(server.iSum == 0); // Drop the client. This shouldn't cause a problem for the already-running RPCs. { auto drop = kj::mv(client); } while (!finishPromise.poll(waitScope)) { KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); } finishPromise.wait(waitScope); KJ_EXPECT(server.iSum == 579); } KJ_TEST("Dropping capability during call doesn't destroy server") { class TestInterfaceImpl final: public test::TestInterface::Server { // An object which increments a count in the constructor and decrements it in the destructor, // to detect when it is destroyed. The object's foo() method also sets a fulfiller to use to // cause the method to complete. public: TestInterfaceImpl(uint& count, kj::Maybe>>& fulfillerSlot) : count(count), fulfillerSlot(fulfillerSlot) { ++count; } ~TestInterfaceImpl() noexcept(false) { --count; } kj::Promise foo(FooContext context) override { auto paf = kj::newPromiseAndFulfiller(); fulfillerSlot = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } private: uint& count; kj::Maybe>>& fulfillerSlot; }; class TestBootstrapImpl final: public test::TestMoreStuff::Server { // Bootstrap object which just vends instances of `TestInterfaceImpl`. public: TestBootstrapImpl(uint& count, kj::Maybe>>& fulfillerSlot) : count(count), fulfillerSlot(fulfillerSlot) {} kj::Promise getHeld(GetHeldContext context) override { context.initResults().setCap(kj::heap(count, fulfillerSlot)); return kj::READY_NOW; } private: uint& count; kj::Maybe>>& fulfillerSlot; }; kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newTwoWayPipe(); uint count = 0; kj::Maybe>> fulfillerSlot; test::TestMoreStuff::Client bootstrap = kj::heap(count, fulfillerSlot); TwoPartyClient tpClient(*pipe.ends[0]); TwoPartyClient tpServer(*pipe.ends[1], kj::mv(bootstrap), rpc::twoparty::Side::SERVER); auto cap = tpClient.bootstrap().castAs().getHeldRequest().send().getCap(); waitScope.poll(); auto promise = cap.fooRequest().send(); KJ_EXPECT(!promise.poll(waitScope)); KJ_EXPECT(count == 1); KJ_EXPECT(fulfillerSlot != nullptr); // Dropping the capability should not destroy the server as long as the call is still // outstanding. {auto drop = kj::mv(cap);} KJ_EXPECT(!promise.poll(waitScope)); KJ_EXPECT(count == 1); // Cancelling the call still should not destroy the server because the call is not marked to // allow cancellation. So the call should keep running. {auto drop = kj::mv(promise);} waitScope.poll(); KJ_EXPECT(count == 1); // When the call completes, only then should the server be dropped. KJ_ASSERT_NONNULL(fulfillerSlot)->fulfill(); waitScope.poll(); KJ_EXPECT(count == 0); } RemotePromise getCallSequence( test::TestCallOrder::Client& client, uint expected) { auto req = client.getCallSequenceRequest(); req.setExpected(expected); return req.send(); } KJ_TEST("Two-hop embargo") { // Copied from `TEST(Rpc, Embargo)` in `rpc-test.c++`, adapted to involve a two-hop path through // a proxy. This tests what happens when disembargoes on multiple hops are happening in parallel. kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0, handleCount = 0; // Set up two two-party RPC connections in series. The middle node just proxies requests through. auto frontPipe = kj::newTwoWayPipe(); auto backPipe = kj::newTwoWayPipe(); TwoPartyClient tpClient(*frontPipe.ends[0]); TwoPartyClient proxyBack(*backPipe.ends[0]); TwoPartyClient proxyFront(*frontPipe.ends[1], proxyBack.bootstrap(), rpc::twoparty::Side::SERVER); TwoPartyClient tpServer(*backPipe.ends[1], kj::heap(callCount, handleCount), rpc::twoparty::Side::SERVER); // Perform some logic that does a bunch of promise pipelining, including passing a capability // from the client to the server and back to the client, and making promise-pipelined calls on // that capability. This should exercise the promise resolution and disembargo code. auto client = tpClient.bootstrap().castAs(); auto cap = test::TestCallOrder::Client(kj::heap()); auto earlyCall = client.getCallSequenceRequest().send(); auto echoRequest = client.echoRequest(); echoRequest.setCap(cap); auto echo = echoRequest.send(); auto pipeline = echo.getCap(); auto call0 = getCallSequence(pipeline, 0); auto call1 = getCallSequence(pipeline, 1); earlyCall.wait(waitScope); auto call2 = getCallSequence(pipeline, 2); auto resolved = echo.wait(waitScope).getCap(); auto call3 = getCallSequence(pipeline, 3); auto call4 = getCallSequence(pipeline, 4); auto call5 = getCallSequence(pipeline, 5); EXPECT_EQ(0, call0.wait(waitScope).getN()); EXPECT_EQ(1, call1.wait(waitScope).getN()); EXPECT_EQ(2, call2.wait(waitScope).getN()); EXPECT_EQ(3, call3.wait(waitScope).getN()); EXPECT_EQ(4, call4.wait(waitScope).getN()); EXPECT_EQ(5, call5.wait(waitScope).getN()); } class TestCallOrderImplAsPromise final: public test::TestCallOrder::Server { // This is an implementation of TestCallOrder that presents itself as a promise by implementing // `shortenPath()`, although it never resolves to anything (`shortenPath()` never completes). // This tests deeper code paths in promise resolution and embargo code. public: template TestCallOrderImplAsPromise(Params&&... params): inner(kj::fwd(params)...) {} kj::Promise getCallSequence(GetCallSequenceContext context) override { return inner.getCallSequence(context); } kj::Maybe> shortenPath() override { // Make this object appear to be a promise. return kj::Promise(kj::NEVER_DONE); } private: TestCallOrderImpl inner; }; KJ_TEST("Two-hop embargo") { // Same as above, but the eventual resolution is itself a promise. This verifies that // handleDisembargo() only waits for the target to resolve back to the capability that the // disembargo should reflect to, but not beyond that. kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0, handleCount = 0; // Set up two two-party RPC connections in series. The middle node just proxies requests through. auto frontPipe = kj::newTwoWayPipe(); auto backPipe = kj::newTwoWayPipe(); TwoPartyClient tpClient(*frontPipe.ends[0]); TwoPartyClient proxyBack(*backPipe.ends[0]); TwoPartyClient proxyFront(*frontPipe.ends[1], proxyBack.bootstrap(), rpc::twoparty::Side::SERVER); TwoPartyClient tpServer(*backPipe.ends[1], kj::heap(callCount, handleCount), rpc::twoparty::Side::SERVER); // Perform some logic that does a bunch of promise pipelining, including passing a capability // from the client to the server and back to the client, and making promise-pipelined calls on // that capability. This should exercise the promise resolution and disembargo code. auto client = tpClient.bootstrap().castAs(); auto cap = test::TestCallOrder::Client(kj::heap()); auto earlyCall = client.getCallSequenceRequest().send(); auto echoRequest = client.echoRequest(); echoRequest.setCap(cap); auto echo = echoRequest.send(); auto pipeline = echo.getCap(); auto call0 = getCallSequence(pipeline, 0); auto call1 = getCallSequence(pipeline, 1); earlyCall.wait(waitScope); auto call2 = getCallSequence(pipeline, 2); auto resolved = echo.wait(waitScope).getCap(); auto call3 = getCallSequence(pipeline, 3); auto call4 = getCallSequence(pipeline, 4); auto call5 = getCallSequence(pipeline, 5); EXPECT_EQ(0, call0.wait(waitScope).getN()); EXPECT_EQ(1, call1.wait(waitScope).getN()); EXPECT_EQ(2, call2.wait(waitScope).getN()); EXPECT_EQ(3, call3.wait(waitScope).getN()); EXPECT_EQ(4, call4.wait(waitScope).getN()); EXPECT_EQ(5, call5.wait(waitScope).getN()); } } // namespace } // namespace _ } // namespace capnp capnproto-c++-1.1.0/src/capnp/any-test.c++0000644000175000017500000003672314527152321020705 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "any.h" #include "message.h" #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { TEST(Any, AnyPointer) { MallocMessageBuilder builder; auto root = builder.getRoot(); initTestMessage(root.getAnyPointerField().initAs()); checkTestMessage(root.getAnyPointerField().getAs()); checkTestMessage(root.asReader().getAnyPointerField().getAs()); root.getAnyPointerField().setAs("foo"); EXPECT_EQ("foo", root.getAnyPointerField().getAs()); EXPECT_EQ("foo", root.asReader().getAnyPointerField().getAs()); root.getAnyPointerField().setAs(data("foo")); EXPECT_EQ(data("foo"), root.getAnyPointerField().getAs()); EXPECT_EQ(data("foo"), root.asReader().getAnyPointerField().getAs()); { root.getAnyPointerField().setAs>({123, 456, 789}); { List::Builder list = root.getAnyPointerField().getAs>(); ASSERT_EQ(3u, list.size()); EXPECT_EQ(123u, list[0]); EXPECT_EQ(456u, list[1]); EXPECT_EQ(789u, list[2]); } { List::Reader list = root.asReader().getAnyPointerField().getAs>(); ASSERT_EQ(3u, list.size()); EXPECT_EQ(123u, list[0]); EXPECT_EQ(456u, list[1]); EXPECT_EQ(789u, list[2]); } } { root.getAnyPointerField().setAs>({"foo", "bar"}); { List::Builder list = root.getAnyPointerField().getAs>(); ASSERT_EQ(2u, list.size()); EXPECT_EQ("foo", list[0]); EXPECT_EQ("bar", list[1]); } { List::Reader list = root.asReader().getAnyPointerField().getAs>(); ASSERT_EQ(2u, list.size()); EXPECT_EQ("foo", list[0]); EXPECT_EQ("bar", list[1]); } } { { List::Builder list = root.getAnyPointerField().initAs>(2); ASSERT_EQ(2u, list.size()); initTestMessage(list[0]); } { List::Builder list = root.getAnyPointerField().getAs>(); ASSERT_EQ(2u, list.size()); checkTestMessage(list[0]); checkTestMessageAllZero(list[1]); } { List::Reader list = root.asReader().getAnyPointerField().getAs>(); ASSERT_EQ(2u, list.size()); checkTestMessage(list[0]); checkTestMessageAllZero(list[1]); } } } TEST(Any, AnyStruct) { MallocMessageBuilder builder; auto root = builder.getRoot(); initTestMessage(root.getAnyPointerField().initAs()); checkTestMessage(root.getAnyPointerField().getAs()); checkTestMessage(root.asReader().getAnyPointerField().getAs()); auto allTypes = root.getAnyPointerField().getAs().as(); auto allTypesReader = root.getAnyPointerField().getAs().asReader().as(); allTypes.setInt32Field(100); EXPECT_EQ(100, allTypes.getInt32Field()); EXPECT_EQ(100, allTypesReader.getInt32Field()); EXPECT_EQ(48, root.getAnyPointerField().getAs().getDataSection().size()); EXPECT_EQ(20, root.getAnyPointerField().getAs().getPointerSection().size()); EXPECT_EQ(48, root.getAnyPointerField().asReader().getAs().getDataSection().size()); EXPECT_EQ(20, root.getAnyPointerField().asReader().getAs().getPointerSection().size()); auto b = toAny(root.getAnyPointerField().getAs()); EXPECT_EQ(48, b.getDataSection().size()); EXPECT_EQ(20, b.getPointerSection().size()); #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h. b = root.getAnyPointerField().getAs(); EXPECT_EQ(48, b.getDataSection().size()); EXPECT_EQ(20, b.getPointerSection().size()); #endif auto r = toAny(root.getAnyPointerField().getAs().asReader()); EXPECT_EQ(48, r.getDataSection().size()); EXPECT_EQ(20, r.getPointerSection().size()); r = toAny(root.getAnyPointerField().getAs()).asReader(); EXPECT_EQ(48, r.getDataSection().size()); EXPECT_EQ(20, r.getPointerSection().size()); #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h. r = root.getAnyPointerField().getAs().asReader(); EXPECT_EQ(48, r.getDataSection().size()); EXPECT_EQ(20, r.getPointerSection().size()); #endif { MallocMessageBuilder b2; auto root2 = b2.getRoot(); auto sb = root2.getAnyPointerField().initAsAnyStruct( r.getDataSection().size() / 8, r.getPointerSection().size()); EXPECT_EQ(48, sb.getDataSection().size()); EXPECT_EQ(20, sb.getPointerSection().size()); // TODO: is there a higher-level API for this? memcpy(sb.getDataSection().begin(), r.getDataSection().begin(), r.getDataSection().size()); } { auto ptrs = r.getPointerSection(); EXPECT_EQ("foo", ptrs[0].getAs()); EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs().asChars())); EXPECT_EQ("xyzzy", ptrs[15].getAs>()[1]); } { auto ptrs = b.getPointerSection(); EXPECT_EQ("foo", ptrs[0].getAs()); EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs().asChars())); EXPECT_EQ("xyzzy", ptrs[15].getAs>()[1]); } } TEST(Any, AnyList) { MallocMessageBuilder builder; auto root = builder.getRoot(); List::Builder b = root.getAnyPointerField().initAs>(2); initTestMessage(b[0]); auto ptr = root.getAnyPointerField().getAs(); EXPECT_EQ(2, ptr.size()); EXPECT_EQ(48, ptr.as>()[0].getDataSection().size()); EXPECT_EQ(20, ptr.as>()[0].getPointerSection().size()); auto readPtr = root.getAnyPointerField().asReader().getAs(); EXPECT_EQ(2, readPtr.size()); EXPECT_EQ(48, readPtr.as>()[0].getDataSection().size()); EXPECT_EQ(20, readPtr.as>()[0].getPointerSection().size()); auto alb = toAny(root.getAnyPointerField().getAs>()); EXPECT_EQ(2, alb.size()); EXPECT_EQ(48, alb.as>()[0].getDataSection().size()); EXPECT_EQ(20, alb.as>()[0].getPointerSection().size()); #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h. alb = root.getAnyPointerField().getAs>(); EXPECT_EQ(2, alb.size()); EXPECT_EQ(48, alb.as>()[0].getDataSection().size()); EXPECT_EQ(20, alb.as>()[0].getPointerSection().size()); #endif auto alr = toAny(root.getAnyPointerField().getAs>().asReader()); EXPECT_EQ(2, alr.size()); EXPECT_EQ(48, alr.as>()[0].getDataSection().size()); EXPECT_EQ(20, alr.as>()[0].getPointerSection().size()); alr = toAny(root.getAnyPointerField().getAs>()).asReader(); EXPECT_EQ(2, alr.size()); EXPECT_EQ(48, alr.as>()[0].getDataSection().size()); EXPECT_EQ(20, alr.as>()[0].getPointerSection().size()); #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h. alr = root.getAnyPointerField().getAs>().asReader(); EXPECT_EQ(2, alr.size()); EXPECT_EQ(48, alr.as>()[0].getDataSection().size()); EXPECT_EQ(20, alr.as>()[0].getPointerSection().size()); #endif } TEST(Any, AnyStructListCapInSchema) { MallocMessageBuilder builder; auto root = builder.getRoot(); { initTestMessage(root.initAnyStructFieldAs()); AnyStruct::Builder anyStruct = root.getAnyStructField(); checkTestMessage(anyStruct.as()); checkTestMessage(anyStruct.asReader().as()); EXPECT_TRUE(root.hasAnyStructField()); auto orphan = root.disownAnyStructField(); checkTestMessage(orphan.getReader().as()); EXPECT_FALSE(root.hasAnyStructField()); root.adoptAnyStructField(kj::mv(orphan)); EXPECT_TRUE(root.hasAnyStructField()); checkTestMessage(root.getAnyStructField().as()); } { List::Builder list = root.initAnyListFieldAs>(3); list.set(0, 123); list.set(1, 456); list.set(2, 789); AnyList::Builder anyList = root.getAnyListField(); checkList(anyList.as>(), {123, 456, 789}); EXPECT_TRUE(root.hasAnyListField()); auto orphan = root.disownAnyListField(); checkList(orphan.getReader().as>(), {123, 456, 789}); EXPECT_FALSE(root.hasAnyListField()); root.adoptAnyListField(kj::mv(orphan)); EXPECT_TRUE(root.hasAnyListField()); checkList(root.getAnyListField().as>(), {123, 456, 789}); } #if !CAPNP_LITE // This portion of the test relies on a Client, not present in lite-mode. { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; root.setCapabilityField(kj::heap(callCount)); Capability::Client client = root.getCapabilityField(); auto req = client.castAs().fooRequest(); req.setI(123); req.setJ(true); req.send().wait(waitScope); EXPECT_EQ(1, callCount); } #endif } KJ_TEST("Builder::isStruct() does not corrupt segment pointer") { MallocMessageBuilder builder(1); // small first segment auto root = builder.getRoot(); // Do a lot of allocations so that there is likely a segment with a decent // amount of free space. initTestMessage(root.initAs()); // This will probably get allocated in a segment that still has room for the // Data allocation below. root.initAs(); // At one point, this caused root.builder.segment to point to the segment // where the struct is allocated, rather than segment where the root pointer // lives, i.e. segment zero. EXPECT_TRUE(root.isStruct()); // If root.builder.segment points to the wrong segment and that segment has free // space, then this triggers a DREQUIRE failure in WirePointer::setKindAndTarget(). root.initAs(1); } TEST(Any, Equals) { MallocMessageBuilder builderA; auto rootA = builderA.getRoot(); auto anyA = builderA.getRoot(); initTestMessage(rootA); MallocMessageBuilder builderB; auto rootB = builderB.getRoot(); auto anyB = builderB.getRoot(); initTestMessage(rootB); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootA.setBoolField(false); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootB.setBoolField(false); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootB.setEnumField(test::TestEnum::GARPLY); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootA.setEnumField(test::TestEnum::GARPLY); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootA.getStructField().setTextField("buzz"); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootB.getStructField().setTextField("buzz"); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootA.initVoidList(3); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootB.initVoidList(3); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootA.getBoolList().set(2, true); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootB.getBoolList().set(2, true); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); rootB.getStructList()[1].setTextField("my NEW structlist 2"); EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB)); rootA.getStructList()[1].setTextField("my NEW structlist 2"); EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB)); } KJ_TEST("Bit list with nonzero pad bits") { AlignedData<2> segment1 = {{ 0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, // eleven bit-sized elements 0xee, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // twelfth bit is set! }}; kj::ArrayPtr segments1[1] = { kj::arrayPtr(segment1.words, 2) }; SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1)); AlignedData<2> segment2 = {{ 0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, // eleven bit-sized elements 0xee, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // twelfth bit is not set }}; kj::ArrayPtr segments2[1] = { kj::arrayPtr(segment2.words, 2) }; SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1)); // Should be equal, despite nonzero padding. KJ_ASSERT(message1.getRoot() == message2.getRoot()); } KJ_TEST("Pointer list unequal to struct list") { AlignedData<1> segment1 = {{ // list with zero pointer-sized elements 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments1[1] = { kj::arrayPtr(segment1.words, 1) }; SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1)); AlignedData<2> segment2 = {{ // struct list of length zero 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // struct list tag, zero elements 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments2[1] = { kj::arrayPtr(segment2.words, 2) }; SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1)); EXPECT_EQ(Equality::NOT_EQUAL, message1.getRoot().equals(message2.getRoot())); } KJ_TEST("Truncating non-null pointer fields does not preserve equality") { AlignedData<3> segment1 = {{ // list with one data word and one pointer field 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, // data word 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, // non-null pointer to zero-sized struct 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments1[1] = { kj::arrayPtr(segment1.words, 3) }; SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1)); AlignedData<2> segment2 = {{ // list with one data word and zero pointers 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // data word 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, }}; kj::ArrayPtr segments2[1] = { kj::arrayPtr(segment2.words, 2) }; SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1)); EXPECT_EQ(Equality::NOT_EQUAL, message1.getRoot().equals(message2.getRoot())); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/stream.capnp.h0000644000175000017500000000633114731562162021410 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: stream.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(995f9a3377c0b16e); } // namespace schemas } // namespace capnp namespace capnp { struct StreamResult { StreamResult() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(995f9a3377c0b16e, 0, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class StreamResult::Reader { public: typedef StreamResult Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class StreamResult::Builder { public: typedef StreamResult Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class StreamResult::Pipeline { public: typedef StreamResult Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/rpc.capnp0000644000175000017500000024742714712011043020452 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xb312981b2552a250; # Recall that Cap'n Proto RPC allows messages to contain references to remote objects that # implement interfaces. These references are called "capabilities", because they both designate # the remote object to use and confer permission to use it. # # Recall also that Cap'n Proto RPC has the feature that when a method call itself returns a # capability, the caller can begin calling methods on that capability _before the first call has # returned_. The caller essentially sends a message saying "Hey server, as soon as you finish # that previous call, do this with the result!". Cap'n Proto's RPC protocol makes this possible. # # The protocol is significantly more complicated than most RPC protocols. However, this is # implementation complexity that underlies an easy-to-grasp higher-level model of object oriented # programming. That is, just like TCP is a surprisingly complicated protocol that implements a # conceptually-simple byte stream abstraction, Cap'n Proto is a surprisingly complicated protocol # that implements a conceptually-simple object abstraction. # # Cap'n Proto RPC is based heavily on CapTP, the object-capability protocol used by the E # programming language: # http://www.erights.org/elib/distrib/captp/index.html # # Cap'n Proto RPC takes place between "vats". A vat hosts some set of objects and talks to other # vats through direct bilateral connections. Typically, there is a 1:1 correspondence between vats # and processes (in the unix sense of the word), although this is not strictly always true (one # process could run multiple vats, or a distributed virtual vat might live across many processes). # # Cap'n Proto does not distinguish between "clients" and "servers" -- this is up to the application. # Either end of any connection can potentially hold capabilities pointing to the other end, and # can call methods on those capabilities. In the doc comments below, we use the words "sender" # and "receiver". These refer to the sender and receiver of an instance of the struct or field # being documented. Sometimes we refer to a "third-party" that is neither the sender nor the # receiver. Documentation is generally written from the point of view of the sender. # # It is generally up to the vat network implementation to securely verify that connections are made # to the intended vat as well as to encrypt transmitted data for privacy and integrity. See the # `VatNetwork` example interface near the end of this file. # # When a new connection is formed, the only interesting things that can be done are to send a # `Bootstrap` (level 0) or `Accept` (level 3) message. # # Unless otherwise specified, messages must be delivered to the receiving application in the same # order in which they were initiated by the sending application. The goal is to support "E-Order", # which states that two calls made on the same reference must be delivered in the order which they # were made: # http://erights.org/elib/concurrency/partial-order.html # # Since the full protocol is complicated, we define multiple levels of support that an # implementation may target. For many applications, level 1 support will be sufficient. # Comments in this file indicate which level requires the corresponding feature to be # implemented. # # * **Level 0:** The implementation does not support object references. Only the bootstrap interface # can be called. At this level, the implementation does not support object-oriented protocols and # is similar in complexity to JSON-RPC or Protobuf services. This level should be considered only # a temporary stepping-stone toward level 1 as the lack of object references drastically changes # how protocols are designed. Applications _should not_ attempt to design their protocols around # the limitations of level 0 implementations. # # * **Level 1:** The implementation supports simple bilateral interaction with object references # and promise pipelining, but interactions between three or more parties are supported only via # proxying of objects. E.g. if Alice (in Vat A) wants to send Bob (in Vat B) a capability # pointing to Carol (in Vat C), Alice must create a proxy of Carol within Vat A and send Bob a # reference to that; Bob cannot form a direct connection to Carol. Level 1 implementations do # not support checking if two capabilities received from different vats actually point to the # same object ("join"), although they should be able to do this check on capabilities received # from the same vat. # # * **Level 2:** The implementation supports saving persistent capabilities -- i.e. capabilities # that remain valid even after disconnect, and can be restored on a future connection. When a # capability is saved, the requester receives a `SturdyRef`, which is a token that can be used # to restore the capability later. # # * **Level 3:** The implementation supports three-way interactions. That is, if Alice (in Vat A) # sends Bob (in Vat B) a capability pointing to Carol (in Vat C), then Vat B will automatically # form a direct connection to Vat C rather than have requests be proxied through Vat A. # # * **Level 4:** The entire protocol is implemented, including joins (checking if two capabilities # are equivalent). # # Note that an implementation must also support specific networks (transports), as described in # the "Network-specific Parameters" section below. An implementation might have different levels # depending on the network used. # # New implementations of Cap'n Proto should start out targeting the simplistic two-party network # type as defined in `rpc-twoparty.capnp`. With this network type, level 3 is irrelevant and # levels 2 and 4 are much easier than usual to implement. When such an implementation is paired # with a container proxy, the contained app effectively gets to make full use of the proxy's # network at level 4. And since Cap'n Proto IPC is extremely fast, it may never make sense to # bother implementing any other vat network protocol -- just use the correct container type and get # it for free. using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("capnp::rpc"); # ======================================================================================== # The Four Tables # # Cap'n Proto RPC connections are stateful (although an application built on Cap'n Proto could # export a stateless interface). As in CapTP, for each open connection, a vat maintains four state # tables: questions, answers, imports, and exports. See the diagram at: # http://www.erights.org/elib/distrib/captp/4tables.html # # The question table corresponds to the other end's answer table, and the imports table corresponds # to the other end's exports table. # # The entries in each table are identified by ID numbers (defined below as 32-bit integers). These # numbers are always specific to the connection; a newly-established connection starts with no # valid IDs. Since low-numbered IDs will pack better, it is suggested that IDs be assigned like # Unix file descriptors -- prefer the lowest-number ID that is currently available. # # IDs in the questions/answers tables are chosen by the questioner and generally represent method # calls that are in progress. # # IDs in the imports/exports tables are chosen by the exporter and generally represent objects on # which methods may be called. Exports may be "settled", meaning the exported object is an actual # object living in the exporter's vat, or they may be "promises", meaning the exported object is # the as-yet-unknown result of an ongoing operation and will eventually be resolved to some other # object once that operation completes. Calls made to a promise will be forwarded to the eventual # target once it is known. The eventual replacement object does *not* get the same ID as the # promise, as it may turn out to be an object that is already exported (so already has an ID) or # may even live in a completely different vat (and so won't get an ID on the same export table # at all). # # IDs can be reused over time. To make this safe, we carefully define the lifetime of IDs. Since # messages using the ID could be traveling in both directions simultaneously, we must define the # end of life of each ID _in each direction_. The ID is only safe to reuse once it has been # released by both sides. # # When a Cap'n Proto connection is lost, everything on the four tables is lost. All questions are # canceled and throw exceptions. All imports become broken (all future calls to them throw # exceptions). All exports and answers are implicitly released. The only things not lost are # persistent capabilities (`SturdyRef`s). The application must plan for this and should respond by # establishing a new connection and restoring from these persistent capabilities. using QuestionId = UInt32; # **(level 0)** # # Identifies a question in the sender's question table (which corresponds to the receiver's answer # table). The questioner (caller) chooses an ID when making a call. The ID remains valid in # caller -> callee messages until a Finish message is sent, and remains valid in callee -> caller # messages until a Return message is sent. using AnswerId = QuestionId; # **(level 0)** # # Identifies an answer in the sender's answer table (which corresponds to the receiver's question # table). # # AnswerId is physically equivalent to QuestionId, since the question and answer tables correspond, # but we define a separate type for documentation purposes: we always use the type representing # the sender's point of view. using ExportId = UInt32; # **(level 1)** # # Identifies an exported capability or promise in the sender's export table (which corresponds # to the receiver's import table). The exporter chooses an ID before sending a capability over the # wire. If the capability is already in the table, the exporter should reuse the same ID. If the # ID is a promise (as opposed to a settled capability), this must be indicated at the time the ID # is introduced (e.g. by using `senderPromise` instead of `senderHosted` in `CapDescriptor`); in # this case, the importer shall expect a later `Resolve` message that replaces the promise. # # ExportId/ImportIds are subject to reference counting. Whenever an `ExportId` is sent over the # wire (from the exporter to the importer), the export's reference count is incremented (unless # otherwise specified). The reference count is later decremented by a `Release` message. Since # the `Release` message can specify an arbitrary number by which to reduce the reference count, the # importer should usually batch reference decrements and only send a `Release` when it believes the # reference count has hit zero. Of course, it is possible that a new reference to the export is # in-flight at the time that the `Release` message is sent, so it is necessary for the exporter to # keep track of the reference count on its end as well to avoid race conditions. # # When a connection is lost, all exports are implicitly released. It is not possible to restore # a connection state after disconnect (although a transport layer could implement a concept of # persistent connections if it is transparent to the RPC layer). using ImportId = ExportId; # **(level 1)** # # Identifies an imported capability or promise in the sender's import table (which corresponds to # the receiver's export table). # # ImportId is physically equivalent to ExportId, since the export and import tables correspond, # but we define a separate type for documentation purposes: we always use the type representing # the sender's point of view. # # An `ImportId` remains valid in importer -> exporter messages until the importer has sent # `Release` messages that (it believes) have reduced the reference count to zero. # ======================================================================================== # Messages struct Message { # An RPC connection is a bi-directional stream of Messages. union { unimplemented @0 :Message; # The sender previously received this message from the peer but didn't understand it or doesn't # yet implement the functionality that was requested. So, the sender is echoing the message # back. In some cases, the receiver may be able to recover from this by pretending the sender # had taken some appropriate "null" action. # # For example, say `resolve` is received by a level 0 implementation (because a previous call # or return happened to contain a promise). The level 0 implementation will echo it back as # `unimplemented`. The original sender can then simply release the cap to which the promise # had resolved, thus avoiding a leak. # # For any message type that introduces a question, if the message comes back unimplemented, # the original sender may simply treat it as if the question failed with an exception. # # In cases where there is no sensible way to react to an `unimplemented` message (without # resource leaks or other serious problems), the connection may need to be aborted. This is # a gray area; different implementations may take different approaches. abort @1 :Exception; # Sent when a connection is being aborted due to an unrecoverable error. This could be e.g. # because the sender received an invalid or nonsensical message or because the sender had an # internal error. The sender will shut down the outgoing half of the connection after `abort` # and will completely close the connection shortly thereafter (it's up to the sender how much # of a time buffer they want to offer for the client to receive the `abort` before the # connection is reset). # Level 0 features ----------------------------------------------- bootstrap @8 :Bootstrap; # Request the peer's bootstrap interface. call @2 :Call; # Begin a method call. return @3 :Return; # Complete a method call. finish @4 :Finish; # Release a returned answer / cancel a call. # Level 1 features ----------------------------------------------- resolve @5 :Resolve; # Resolve a previously-sent promise. release @6 :Release; # Release a capability so that the remote object can be deallocated. disembargo @13 :Disembargo; # Lift an embargo used to enforce E-order over promise resolution. # Level 2 features ----------------------------------------------- obsoleteSave @7 :AnyPointer; # Obsolete request to save a capability, resulting in a SturdyRef. This has been replaced # by the `Persistent` interface defined in `persistent.capnp`. This operation was never # implemented. obsoleteDelete @9 :AnyPointer; # Obsolete way to delete a SturdyRef. This operation was never implemented. # Level 3 features ----------------------------------------------- provide @10 :Provide; # Provide a capability to a third party. accept @11 :Accept; # Accept a capability provided by a third party. # Level 4 features ----------------------------------------------- join @12 :Join; # Directly connect to the common root of two or more proxied caps. } } # Level 0 message types ---------------------------------------------- struct Bootstrap { # **(level 0)** # # Get the "bootstrap" interface exported by the remote vat. # # For level 0, 1, and 2 implementations, the "bootstrap" interface is simply the main interface # exported by a vat. If the vat acts as a server fielding connections from clients, then the # bootstrap interface defines the basic functionality available to a client when it connects. # The exact interface definition obviously depends on the application. # # We call this a "bootstrap" because in an ideal Cap'n Proto world, bootstrap interfaces would # never be used. In such a world, any time you connect to a new vat, you do so because you # received an introduction from some other vat (see `ThirdPartyCapId`). Thus, the first message # you send is `Accept`, and further communications derive from there. `Bootstrap` is not used. # # In such an ideal world, DNS itself would support Cap'n Proto -- performing a DNS lookup would # actually return a new Cap'n Proto capability, thus introducing you to the target system via # level 3 RPC. Applications would receive the capability to talk to DNS in the first place as # an initial endowment or part of a Powerbox interaction. Therefore, an app can form arbitrary # connections without ever using `Bootstrap`. # # Of course, in the real world, DNS is not Cap'n-Proto-based, and we don't want Cap'n Proto to # require a whole new internet infrastructure to be useful. Therefore, we offer bootstrap # interfaces as a way to get up and running without a level 3 introduction. Thus, bootstrap # interfaces are used to "bootstrap" from other, non-Cap'n-Proto-based means of service discovery, # such as legacy DNS. # # Note that a vat need not provide a bootstrap interface, and in fact many vats (especially those # acting as clients) do not. In this case, the vat should either reply to `Bootstrap` with a # `Return` indicating an exception, or should return a dummy capability with no methods. questionId @0 :QuestionId; # A new question ID identifying this request, which will eventually receive a Return message # containing the restored capability. deprecatedObjectId @1 :AnyPointer; # ** DEPRECATED ** # # A Vat may export multiple bootstrap interfaces. In this case, `deprecatedObjectId` specifies # which one to return. If this pointer is null, then the default bootstrap interface is returned. # # As of version 0.5, use of this field is deprecated. If a service wants to export multiple # bootstrap interfaces, it should instead define a single bootstrap interface that has methods # that return each of the other interfaces. # # **History** # # In the first version of Cap'n Proto RPC (0.4.x) the `Bootstrap` message was called `Restore`. # At the time, it was thought that this would eventually serve as the way to restore SturdyRefs # (level 2). Meanwhile, an application could offer its "main" interface on a well-known # (non-secret) SturdyRef. # # Since level 2 RPC was not implemented at the time, the `Restore` message was in practice only # used to obtain the main interface. Since most applications had only one main interface that # they wanted to restore, they tended to designate this with a null `objectId`. # # Unfortunately, the earliest version of the EZ RPC interfaces set a precedent of exporting # multiple main interfaces by allowing them to be exported under string names. In this case, # `objectId` was a Text value specifying the name. # # All of this proved problematic for several reasons: # # - The arrangement assumed that a client wishing to restore a SturdyRef would know exactly what # machine to connect to and would be able to immediately restore a SturdyRef on connection. # However, in practice, the ability to restore SturdyRefs is itself a capability that may # require going through an authentication process to obtain. Thus, it makes more sense to # define a "restorer service" as a full Cap'n Proto interface. If this restorer interface is # offered as the vat's bootstrap interface, then this is equivalent to the old arrangement. # # - Overloading "Restore" for the purpose of obtaining well-known capabilities encouraged the # practice of exporting singleton services with string names. If singleton services are desired, # it is better to have one main interface that has methods that can be used to obtain each # service, in order to get all the usual benefits of schemas and type checking. # # - Overloading "Restore" also had a security problem: Often, "main" or "well-known" # capabilities exported by a vat are in fact not public: they are intended to be accessed only # by clients who are capable of forming a connection to the vat. This can lead to trouble if # the client itself has other clients and wishes to forward some `Restore` requests from those # external clients -- it has to be very careful not to allow through `Restore` requests # addressing the default capability. # # For example, consider the case of a sandboxed Sandstorm application and its supervisor. The # application exports a default capability to its supervisor that provides access to # functionality that only the supervisor is supposed to access. Meanwhile, though, applications # may publish other capabilities that may be persistent, in which case the application needs # to field `Restore` requests that could come from anywhere. These requests of course have to # pass through the supervisor, as all communications with the outside world must. But, the # supervisor has to be careful not to honor an external request addressing the application's # default capability, since this capability is privileged. Unfortunately, the default # capability cannot be given an unguessable name, because then the supervisor itself would not # be able to address it! # # As of Cap'n Proto 0.5, `Restore` has been renamed to `Bootstrap` and is no longer planned for # use in restoring SturdyRefs. # # Note that 0.4 also defined a message type called `Delete` that, like `Restore`, addressed a # SturdyRef, but indicated that the client would not restore the ref again in the future. This # operation was never implemented, so it was removed entirely. If a "delete" operation is desired, # it should exist as a method on the same interface that handles restoring SturdyRefs. However, # the utility of such an operation is questionable. You wouldn't be able to rely on it for # garbage collection since a client could always disappear permanently without remembering to # delete all its SturdyRefs, thus leaving them dangling forever. Therefore, it is advisable to # design systems such that SturdyRefs never represent "owned" pointers. # # For example, say a SturdyRef points to an image file hosted on some server. That image file # should also live inside a collection (a gallery, perhaps) hosted on the same server, owned by # a user who can delete the image at any time. If the user deletes the image, the SturdyRef # stops working. On the other hand, if the SturdyRef is discarded, this has no effect on the # existence of the image in its collection. } struct Call { # **(level 0)** # # Message type initiating a method call on a capability. questionId @0 :QuestionId; # A number, chosen by the caller, that identifies this call in future messages. This number # must be different from all other calls originating from the same end of the connection (but # may overlap with question IDs originating from the opposite end). A fine strategy is to use # sequential question IDs, but the recipient should not assume this. # # A question ID can be reused once both: # - A matching Return has been received from the callee. # - A matching Finish has been sent from the caller. target @1 :MessageTarget; # The object that should receive this call. interfaceId @2 :UInt64; # The type ID of the interface being called. Each capability may implement multiple interfaces. methodId @3 :UInt16; # The ordinal number of the method to call within the requested interface. allowThirdPartyTailCall @8 :Bool = false; # Indicates whether or not the receiver is allowed to send a `Return` containing # `acceptFromThirdParty`. Level 3 implementations should set this true. Otherwise, the callee # will have to proxy the return in the case of a tail call to a third-party vat. noPromisePipelining @9 :Bool = false; # If true, the sender promises that it won't make any promise-pipelined calls on the results of # this call. If it breaks this promise, the receiver may throw an arbitrary error from such # calls. # # The receiver may use this as an optimization, by skipping the bookkeeping needed for pipelining # when no pipelined calls are expected. The sender typically sets this to false when the method's # schema does not specify any return capabilities. onlyPromisePipeline @10 :Bool = false; # If true, the sender only plans to use this call to make pipelined calls. The receiver need not # send a `Return` message (but is still allowed to do so). # # Since the sender does not know whether a `Return` will be sent, it must release all state # related to the call when it sends `Finish`. However, in the case that the callee does not # recognize this hint and chooses to send a `Return`, then technically the caller is not allowed # to reuse the question ID until it receives said `Return`. This creates a conundrum: How does # the caller decide when it's OK to reuse the ID? To sidestep the problem, the C++ implementation # uses high-numbered IDs (with the high-order bit set) for such calls, and cycles through the # IDs in order. If all 2^31 IDs in this space are used without ever seeing a `Return`, then the # implementation assumes that the other end is in fact honoring the hint, and the ID counter is # allowed to loop around. If a `Return` is ever seen when `onlyPromisePipeline` was set, then # the implementation stops using this hint. params @4 :Payload; # The call parameters. `params.content` is a struct whose fields correspond to the parameters of # the method. sendResultsTo :union { # Where should the return message be sent? caller @5 :Void; # Send the return message back to the caller (the usual). yourself @6 :Void; # **(level 1)** # # Don't actually return the results to the sender. Instead, hold on to them and await # instructions from the sender regarding what to do with them. In particular, the sender # may subsequently send a `Return` for some other call (which the receiver had previously made # to the sender) with `takeFromOtherQuestion` set. The results from this call are then used # as the results of the other call. # # When `yourself` is used, the receiver must still send a `Return` for the call, but sets the # field `resultsSentElsewhere` in that `Return` rather than including the results. # # This feature can be used to implement tail calls in which a call from Vat A to Vat B ends up # returning the result of a call from Vat B back to Vat A. # # In particular, the most common use case for this feature is when Vat A makes a call to a # promise in Vat B, and then that promise ends up resolving to a capability back in Vat A. # Vat B must forward all the queued calls on that promise back to Vat A, but can set `yourself` # in the calls so that the results need not pass back through Vat B. # # For example: # - Alice, in Vat A, calls foo() on Bob in Vat B. # - Alice makes a pipelined call bar() on the promise returned by foo(). # - Later on, Bob resolves the promise from foo() to point at Carol, who lives in Vat A (next # to Alice). # - Vat B dutifully forwards the bar() call to Carol. Let us call this forwarded call bar'(). # Notice that bar() and bar'() are travelling in opposite directions on the same network # link. # - The `Call` for bar'() has `sendResultsTo` set to `yourself`. # - Vat B sends a `Return` for bar() with `takeFromOtherQuestion` set in place of the results, # with the value set to the question ID of bar'(). Vat B does not wait for bar'() to return, # as doing so would introduce unnecessary round trip latency. # - Vat A receives bar'() and delivers it to Carol. # - When bar'() returns, Vat A sends a `Return` for bar'() to Vat B, with `resultsSentElsewhere` # set in place of results. # - Vat A sends a `Finish` for the bar() call to Vat B. # - Vat B receives the `Finish` for bar() and sends a `Finish` for bar'(). thirdParty @7 :RecipientId; # **(level 3)** # # The call's result should be returned to a different vat. The receiver (the callee) expects # to receive an `Accept` message from the indicated vat, and should return the call's result # to it, rather than to the sender of the `Call`. # # This operates much like `yourself`, above, except that Carol is in a separate Vat C. `Call` # messages are sent from Vat A -> Vat B and Vat B -> Vat C. A `Return` message is sent from # Vat B -> Vat A that contains `acceptFromThirdParty` in place of results. When Vat A sends # an `Accept` to Vat C, it receives back a `Return` containing the call's actual result. Vat C # also sends a `Return` to Vat B with `resultsSentElsewhere`. } } struct Return { # **(level 0)** # # Message type sent from callee to caller indicating that the call has completed. answerId @0 :AnswerId; # Equal to the QuestionId of the corresponding `Call` message. releaseParamCaps @1 :Bool = true; # If true, all capabilities that were in the params should be considered released. The sender # must not send separate `Release` messages for them. Level 0 implementations in particular # should always set this true. This defaults true because if level 0 implementations forget to # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget # to set it to false they'll quickly get errors. # # The receiver should act as if the sender had sent a release message with count=1 for each # CapDescriptor in the original Call message. noFinishNeeded @8 :Bool = false; # If true, the sender does not need the receiver to send a `Finish` message; its answer table # entry has already been cleaned up. This implies that the results do not contain any # capabilities, since the `Finish` message would normally release those capabilities from # promise pipelining responsibility. The caller may still send a `Finish` message if it wants, # which will be silently ignored by the callee. union { results @2 :Payload; # The result. # # For regular method calls, `results.content` points to the result struct. # # For a `Return` in response to an `Accept` or `Bootstrap`, `results` contains a single # capability (rather than a struct), and `results.content` is just a capability pointer with # index 0. A `Finish` is still required in this case. exception @3 :Exception; # Indicates that the call failed and explains why. canceled @4 :Void; # Indicates that the call was canceled due to the caller sending a Finish message # before the call had completed. resultsSentElsewhere @5 :Void; # This is set when returning from a `Call` that had `sendResultsTo` set to something other # than `caller`. # # It doesn't matter too much when this is sent, as the receiver doesn't need to do anything # with it, but the C++ implementation appears to wait for the call to finish before sending # this. takeFromOtherQuestion @6 :QuestionId; # The sender has also sent (before this message) a `Call` with the given question ID and with # `sendResultsTo.yourself` set, and the results of that other call should be used as the # results here. `takeFromOtherQuestion` can only used once per question. acceptFromThirdParty @7 :ThirdPartyCapId; # **(level 3)** # # The caller should contact a third-party vat to pick up the results. An `Accept` message # sent to the vat will return the result. This pairs with `Call.sendResultsTo.thirdParty`. # It should only be used if the corresponding `Call` had `allowThirdPartyTailCall` set. } } struct Finish { # **(level 0)** # # Message type sent from the caller to the callee to indicate: # 1) The questionId will no longer be used in any messages sent by the callee (no further # pipelined requests). # 2) If the call has not returned yet, the caller no longer cares about the result. If nothing # else cares about the result either (e.g. there are no other outstanding calls pipelined on # the result of this one) then the callee may wish to immediately cancel the operation and # send back a Return message with "canceled" set. However, implementations are not required # to support premature cancellation -- instead, the implementation may wait until the call # actually completes and send a normal `Return` message. # # TODO(someday): Should we separate (1) and implicitly releasing result capabilities? It would be # possible and useful to notify the server that it doesn't need to keep around the response to # service pipeline requests even though the caller still wants to receive it / hasn't yet # finished processing it. It could also be useful to notify the server that it need not marshal # the results because the caller doesn't want them anyway, even if the caller is still sending # pipelined calls, although this seems less useful (just saving some bytes on the wire). questionId @0 :QuestionId; # ID of the call whose result is to be released. releaseResultCaps @1 :Bool = true; # If true, all capabilities that were in the results should be considered released. The sender # must not send separate `Release` messages for them. Level 0 implementations in particular # should always set this true. This defaults true because if level 0 implementations forget to # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget # set it false they'll quickly get errors. requireEarlyCancellationWorkaround @2 :Bool = true; # If true, if the RPC system receives this Finish message before the original call has even been # delivered, it should defer cancellation util after delivery. In particular, this gives the # destination object a chance to opt out of cancellation, e.g. as controlled by the # `allowCancellation` annotation defined in `c++.capnp`. # # This is a work-around. Versions 1.0 and up of Cap'n Proto always set this to false. However, # older versions of Cap'n Proto unintentionally exhibited this errant behavior by default, and # as a result programs built with older versions could be inadvertently relying on their peers # to implement the behavior. The purpose of this flag is to let newer versions know when the # peer is an older version, so that it can attempt to work around the issue. # # See also comments in handleFinish() in rpc.c++ for more details. } # Level 1 message types ---------------------------------------------- struct Resolve { # **(level 1)** # # Message type sent to indicate that a previously-sent promise has now been resolved to some other # object (possibly another promise) -- or broken, or canceled. # # Keep in mind that it's possible for a `Resolve` to be sent to a level 0 implementation that # doesn't implement it. For example, a method call or return might contain a capability in the # payload. Normally this is fine even if the receiver is level 0, because they will implicitly # release all such capabilities on return / finish. But if the cap happens to be a promise, then # a follow-up `Resolve` may be sent regardless of this release. The level 0 receiver will reply # with an `unimplemented` message, and the sender (of the `Resolve`) can respond to this as if the # receiver had immediately released any capability to which the promise resolved. # # When implementing promise resolution, it's important to understand how embargos work and the # tricky case of the Tribble 4-way race condition. See the comments for the Disembargo message, # below. promiseId @0 :ExportId; # The ID of the promise to be resolved. # # Unlike all other instances of `ExportId` sent from the exporter, the `Resolve` message does # _not_ increase the reference count of `promiseId`. In fact, it is expected that the receiver # will release the export soon after receiving `Resolve`, and the sender will not send this # `ExportId` again until it has been released and recycled. # # When an export ID sent over the wire (e.g. in a `CapDescriptor`) is indicated to be a promise, # this indicates that the sender will follow up at some point with a `Resolve` message. If the # same `promiseId` is sent again before `Resolve`, still only one `Resolve` is sent. If the # same ID is sent again later _after_ a `Resolve`, it can only be because the export's # reference count hit zero in the meantime and the ID was re-assigned to a new export, therefore # this later promise does _not_ correspond to the earlier `Resolve`. # # If a promise ID's reference count reaches zero before a `Resolve` is sent, the `Resolve` # message may or may not still be sent (the `Resolve` may have already been in-flight when # `Release` was sent, but if the `Release` is received before `Resolve` then there is no longer # any reason to send a `Resolve`). Thus a `Resolve` may be received for a promise of which # the receiver has no knowledge, because it already released it earlier. In this case, the # receiver should simply release the capability to which the promise resolved. union { cap @1 :CapDescriptor; # The object to which the promise resolved. # # The sender promises that from this point forth, until `promiseId` is released, it shall # simply forward all messages to the capability designated by `cap`. This is true even if # `cap` itself happens to designate another promise, and that other promise later resolves -- # messages sent to `promiseId` shall still go to that other promise, not to its resolution. # This is important in the case that the receiver of the `Resolve` ends up sending a # `Disembargo` message towards `promiseId` in order to control message ordering -- that # `Disembargo` really needs to reflect back to exactly the object designated by `cap` even # if that object is itself a promise. exception @2 :Exception; # Indicates that the promise was broken. } } struct Release { # **(level 1)** # # Message type sent to indicate that the sender is done with the given capability and the receiver # can free resources allocated to it. id @0 :ImportId; # What to release. referenceCount @1 :UInt32; # The amount by which to decrement the reference count. The export is only actually released # when the reference count reaches zero. } struct Disembargo { # **(level 1)** # # Message sent to indicate that an embargo on a recently-resolved promise may now be lifted. # # Embargos are used to enforce E-order in the presence of promise resolution. That is, if an # application makes two calls foo() and bar() on the same capability reference, in that order, # the calls should be delivered in the order in which they were made. But if foo() is called # on a promise, and that promise happens to resolve before bar() is called, then the two calls # may travel different paths over the network, and thus could arrive in the wrong order. In # this case, the call to `bar()` must be embargoed, and a `Disembargo` message must be sent along # the same path as `foo()` to ensure that the `Disembargo` arrives after `foo()`. Once the # `Disembargo` arrives, `bar()` can then be delivered. # # There are two particular cases where embargos are important. Consider object Alice, in Vat A, # who holds a promise P, pointing towards Vat B, that eventually resolves to Carol. The two # cases are: # - Carol lives in Vat A, i.e. next to Alice. In this case, Vat A needs to send a `Disembargo` # message that echos through Vat B and back, to ensure that all pipelined calls on the promise # have been delivered. # - Carol lives in a different Vat C. When the promise resolves, a three-party handoff occurs # (see `Provide` and `Accept`, which constitute level 3 of the protocol). In this case, we # piggyback on the state that has already been set up to handle the handoff: the `Accept` # message (from Vat A to Vat C) is embargoed, as are all pipelined messages sent to it, while # a `Disembargo` message is sent from Vat A through Vat B to Vat C. See `Accept.embargo` for # an example. # # Note that in the case where Carol actually lives in Vat B (i.e., the same vat that the promise # already pointed at), no embargo is needed, because the pipelined calls are delivered over the # same path as the later direct calls. # # Keep in mind that promise resolution happens both in the form of Resolve messages as well as # Return messages (which resolve PromisedAnswers). Embargos apply in both cases. # # An alternative strategy for enforcing E-order over promise resolution could be for Vat A to # implement the embargo internally. When Vat A is notified of promise resolution, it could # send a dummy no-op call to promise P and wait for it to complete. Until that call completes, # all calls to the capability are queued locally. This strategy works, but is pessimistic: # in the three-party case, it requires an A -> B -> C -> B -> A round trip before calls can start # being delivered directly to from Vat A to Vat C. The `Disembargo` message allows latency to be # reduced. (In the two-party loopback case, the `Disembargo` message is just a more explicit way # of accomplishing the same thing as a no-op call, but isn't any faster.) # # *The Tribble 4-way Race Condition* # # Any implementation of promise resolution and embargos must be aware of what we call the # "Tribble 4-way race condition", after Dean Tribble, who explained the problem in a lively # Friam meeting. # # Embargos are designed to work in the case where a two-hop path is being shortened to one hop. # But sometimes there are more hops. Imagine that Alice has a reference to a remote promise P1 # that eventually resolves to _another_ remote promise P2 (in a third vat), which _at the same # time_ happens to resolve to Bob (in a fourth vat). In this case, we're shortening from a 3-hop # path (with four parties) to a 1-hop path (Alice -> Bob). # # Extending the embargo/disembargo protocol to be able to shorted multiple hops at once seems # difficult. Instead, we make a rule that prevents this case from coming up: # # One a promise P has been resolved to a remote object reference R, then all further messages # received addressed to P will be forwarded strictly to R. Even if it turns out later that R is # itself a promise, and has resolved to some other object Q, messages sent to P will still be # forwarded to R, not directly to Q (R will of course further forward the messages to Q). # # This rule does not cause a significant performance burden because once P has resolved to R, it # is expected that people sending messages to P will shortly start sending them to R instead and # drop P. P is at end-of-life anyway, so it doesn't matter if it ignores chances to further # optimize its path. # # Note well: the Tribble 4-way race condition does not require each vat to be *distinct*; as long # as each resolution crosses a network boundary the race can occur -- so this concerns even level # 1 implementations, not just level 3 implementations. target @0 :MessageTarget; # What is to be disembargoed. using EmbargoId = UInt32; # Used in `senderLoopback` and `receiverLoopback`, below. context :union { senderLoopback @1 :EmbargoId; # The sender is requesting a disembargo on a promise that is known to resolve back to a # capability hosted by the sender. As soon as the receiver has echoed back all pipelined calls # on this promise, it will deliver the Disembargo back to the sender with `receiverLoopback` # set to the same value as `senderLoopback`. This value is chosen by the sender, and since # it is also consumed be the sender, the sender can use whatever strategy it wants to make sure # the value is unambiguous. # # The receiver must verify that the target capability actually resolves back to the sender's # vat. Otherwise, the sender has committed a protocol error and should be disconnected. receiverLoopback @2 :EmbargoId; # The receiver previously sent a `senderLoopback` Disembargo towards a promise resolving to # this capability, and that Disembargo is now being echoed back. accept @3 :Void; # **(level 3)** # # The sender is requesting a disembargo on a promise that is known to resolve to a third-party # capability that the sender is currently in the process of accepting (using `Accept`). # The receiver of this `Disembargo` has an outstanding `Provide` on said capability. The # receiver should now send a `Disembargo` with `provide` set to the question ID of that # `Provide` message. # # See `Accept.embargo` for an example. provide @4 :QuestionId; # **(level 3)** # # The sender is requesting a disembargo on a capability currently being provided to a third # party. The question ID identifies the `Provide` message previously sent by the sender to # this capability. On receipt, the receiver (the capability host) shall release the embargo # on the `Accept` message that it has received from the third party. See `Accept.embargo` for # an example. } } # Level 2 message types ---------------------------------------------- # See persistent.capnp. # Level 3 message types ---------------------------------------------- struct Provide { # **(level 3)** # # Message type sent to indicate that the sender wishes to make a particular capability implemented # by the receiver available to a third party for direct access (without the need for the third # party to proxy through the sender). # # (In CapTP, `Provide` and `Accept` are methods of the global `NonceLocator` object exported by # every vat. In Cap'n Proto, we bake this into the core protocol.) questionId @0 :QuestionId; # Question ID to be held open until the recipient has received the capability. A result will be # returned once the third party has successfully received the capability. The sender must at some # point send a `Finish` message as with any other call, and that message can be used to cancel the # whole operation. target @1 :MessageTarget; # What is to be provided to the third party. recipient @2 :RecipientId; # Identity of the third party that is expected to pick up the capability. } struct Accept { # **(level 3)** # # Message type sent to pick up a capability hosted by the receiving vat and provided by a third # party. The third party previously designated the capability using `Provide`. # # This message is also used to pick up a redirected return -- see `Return.acceptFromThirdParty`. questionId @0 :QuestionId; # A new question ID identifying this accept message, which will eventually receive a Return # message containing the provided capability (or the call result in the case of a redirected # return). provision @1 :ProvisionId; # Identifies the provided object to be picked up. embargo @2 :Bool; # If true, this accept shall be temporarily embargoed. The resulting `Return` will not be sent, # and any pipelined calls will not be delivered, until the embargo is released. The receiver # (the capability host) will expect the provider (the vat that sent the `Provide` message) to # eventually send a `Disembargo` message with the field `context.provide` set to the question ID # of the original `Provide` message. At that point, the embargo is released and the queued # messages are delivered. # # For example: # - Alice, in Vat A, holds a promise P, which currently points toward Vat B. # - Alice calls foo() on P. The `Call` message is sent to Vat B. # - The promise P in Vat B ends up resolving to Carol, in Vat C. # - Vat B sends a `Provide` message to Vat C, identifying Vat A as the recipient. # - Vat B sends a `Resolve` message to Vat A, indicating that the promise has resolved to a # `ThirdPartyCapId` identifying Carol in Vat C. # - Vat A sends an `Accept` message to Vat C to pick up the capability. Since Vat A knows that # it has an outstanding call to the promise, it sets `embargo` to `true` in the `Accept` # message. # - Vat A sends a `Disembargo` message to Vat B on promise P, with `context.accept` set. # - Alice makes a call bar() to promise P, which is now pointing towards Vat C. Alice doesn't # know anything about the mechanics of promise resolution happening under the hood, but she # expects that bar() will be delivered after foo() because that is the order in which she # initiated the calls. # - Vat A sends the bar() call to Vat C, as a pipelined call on the result of the `Accept` (which # hasn't returned yet, due to the embargo). Since calls to the newly-accepted capability # are embargoed, Vat C does not deliver the call yet. # - At some point, Vat B forwards the foo() call from the beginning of this example on to Vat C. # - Vat B forwards the `Disembargo` from Vat A on to vat C. It sets `context.provide` to the # question ID of the `Provide` message it had sent previously. # - Vat C receives foo() before `Disembargo`, thus allowing it to correctly deliver foo() # before delivering bar(). # - Vat C receives `Disembargo` from Vat B. It can now send a `Return` for the `Accept` from # Vat A, as well as deliver bar(). } # Level 4 message types ---------------------------------------------- struct Join { # **(level 4)** # # Message type sent to implement E.join(), which, given a number of capabilities that are # expected to be equivalent, finds the underlying object upon which they all agree and forms a # direct connection to it, skipping any proxies that may have been constructed by other vats # while transmitting the capability. See: # http://erights.org/elib/equality/index.html # # Note that this should only serve to bypass fully-transparent proxies -- proxies that were # created merely for convenience, without any intention of hiding the underlying object. # # For example, say Bob holds two capabilities hosted by Alice and Carol, but he expects that both # are simply proxies for a capability hosted elsewhere. He then issues a join request, which # operates as follows: # - Bob issues Join requests on both Alice and Carol. Each request contains a different piece # of the JoinKey. # - Alice is proxying a capability hosted by Dana, so forwards the request to Dana's cap. # - Dana receives the first request and sees that the JoinKeyPart is one of two. She notes that # she doesn't have the other part yet, so she records the request and responds with a # JoinResult. # - Alice relays the JoinAnswer back to Bob. # - Carol is also proxying a capability from Dana, and so forwards her Join request to Dana as # well. # - Dana receives Carol's request and notes that she now has both parts of a JoinKey. She # combines them in order to form information needed to form a secure connection to Bob. She # also responds with another JoinResult. # - Bob receives the responses from Alice and Carol. He uses the returned JoinResults to # determine how to connect to Dana and attempts to form the connection. Since Bob and Dana now # agree on a secret key that neither Alice nor Carol ever saw, this connection can be made # securely even if Alice or Carol is conspiring against the other. (If Alice and Carol are # conspiring _together_, they can obviously reproduce the key, but this doesn't matter because # the whole point of the join is to verify that Alice and Carol agree on what capability they # are proxying.) # # If the two capabilities aren't actually proxies of the same object, then the join requests # will come back with conflicting `hostId`s and the join will fail before attempting to form any # connection. questionId @0 :QuestionId; # Question ID used to respond to this Join. (Note that this ID only identifies one part of the # request for one hop; each part has a different ID and relayed copies of the request have # (probably) different IDs still.) # # The receiver will reply with a `Return` whose `results` is a JoinResult. This `JoinResult` # is relayed from the joined object's host, possibly with transformation applied as needed # by the network. # # Like any return, the result must be released using a `Finish`. However, this release # should not occur until the joiner has either successfully connected to the joined object. # Vats relaying a `Join` message similarly must not release the result they receive until the # return they relayed back towards the joiner has itself been released. This allows the # joined object's host to detect when the Join operation is canceled before completing -- if # it receives a `Finish` for one of the join results before the joiner successfully # connects. It can then free any resources it had allocated as part of the join. target @1 :MessageTarget; # The capability to join. keyPart @2 :JoinKeyPart; # A part of the join key. These combine to form the complete join key, which is used to establish # a direct connection. # TODO(before implementing): Change this so that multiple parts can be sent in a single Join # message, so that if multiple join parts are going to cross the same connection they can be sent # together, so that the receive can potentially optimize its handling of them. In the case where # all parts are bundled together, should the recipient be expected to simply return a cap, so # that the caller can immediately start pipelining to it? } # ======================================================================================== # Common structures used in messages struct MessageTarget { # The target of a `Call` or other messages that target a capability. union { importedCap @0 :ImportId; # This message is to a capability or promise previously imported by the caller (exported by # the receiver). promisedAnswer @1 :PromisedAnswer; # This message is to a capability that is expected to be returned by another call that has not # yet been completed. # # At level 0, this is supported only for addressing the result of a previous `Bootstrap`, so # that initial startup doesn't require a round trip. } } struct Payload { # Represents some data structure that might contain capabilities. content @0 :AnyPointer; # Some Cap'n Proto data structure. Capability pointers embedded in this structure index into # `capTable`. capTable @1 :List(CapDescriptor); # Descriptors corresponding to the cap pointers in `content`. } struct CapDescriptor { # **(level 1)** # # When an application-defined type contains an interface pointer, that pointer contains an index # into the message's capability table -- i.e. the `capTable` part of the `Payload`. Each # capability in the table is represented as a `CapDescriptor`. The runtime API should not reveal # the CapDescriptor directly to the application, but should instead wrap it in some kind of # callable object with methods corresponding to the interface that the capability implements. # # Keep in mind that `ExportIds` in a `CapDescriptor` are subject to reference counting. See the # description of `ExportId`. # # Note that it is currently not possible to include a broken capability in the CapDescriptor # table. Instead, create a new export (`senderPromise`) for each broken capability and then # immediately follow the payload-bearing Call or Return message with one Resolve message for each # broken capability, resolving it to an exception. union { none @0 :Void; # There is no capability here. This `CapDescriptor` should not appear in the payload content. # A `none` CapDescriptor can be generated when an application inserts a capability into a # message and then later changes its mind and removes it -- rewriting all of the other # capability pointers may be hard, so instead a tombstone is left, similar to the way a removed # struct or list instance is zeroed out of the message but the space is not reclaimed. # Hopefully this is unusual. senderHosted @1 :ExportId; # The ID of a capability in the sender's export table (receiver's import table). It may be a # newly allocated table entry, or an existing entry (increments the reference count). senderPromise @2 :ExportId; # A promise that the sender will resolve later. The sender will send exactly one Resolve # message at a future point in time to replace this promise. Note that even if the same # `senderPromise` is received multiple times, only one `Resolve` is sent to cover all of # them. If `senderPromise` is released before the `Resolve` is sent, the sender (of this # `CapDescriptor`) may choose not to send the `Resolve` at all. receiverHosted @3 :ImportId; # A capability (or promise) previously exported by the receiver (imported by the sender). receiverAnswer @4 :PromisedAnswer; # A capability expected to be returned in the results of a currently-outstanding call posed # by the sender. thirdPartyHosted @5 :ThirdPartyCapDescriptor; # **(level 3)** # # A capability that lives in neither the sender's nor the receiver's vat. The sender needs # to form a direct connection to a third party to pick up the capability. # # Level 1 and 2 implementations that receive a `thirdPartyHosted` may simply send calls to its # `vine` instead. } attachedFd @6 :UInt8 = 0xff; # If the RPC message in which this CapDescriptor was delivered also had file descriptors # attached, and `fd` is a valid index into the list of attached file descriptors, then # that file descriptor should be attached to this capability. If `attachedFd` is out-of-bounds # for said list, then no FD is attached. # # For example, if the RPC message arrived over a Unix socket, then file descriptors may be # attached by sending an SCM_RIGHTS ancillary message attached to the data bytes making up the # raw message. Receivers who wish to opt into FD passing should arrange to receive SCM_RIGHTS # whenever receiving an RPC message. Senders who wish to send FDs need not verify whether the # receiver knows how to receive them, because the operating system will automatically discard # ancillary messages like SCM_RIGHTS if the receiver doesn't ask to receive them, including # automatically closing any FDs. # # It is up to the application protocol to define what capabilities are expected to have file # descriptors attached, and what those FDs mean. But, for example, an application could use this # to open a file on disk and then transmit the open file descriptor to a sandboxed process that # does not otherwise have permission to access the filesystem directly. This is usually an # optimization: the sending process could instead provide an RPC interface supporting all the # operations needed (such as reading and writing a file), but by passing the file descriptor # directly, the recipient can often perform operations much more efficiently. Application # designers are encouraged to provide such RPC interfaces and automatically fall back to them # when FD passing is not available, so that the application can still work when the parties are # remote over a network. # # An attached FD is most often associated with a `senderHosted` descriptor. It could also make # sense in the case of `thirdPartyHosted`: in this case, the sender is forwarding the FD that # they received from the third party, so that the receiver can start using it without first # interacting with the third party. This is an optional optimization -- the middleman may choose # not to forward capabilities, in which case the receiver will need to complete the handshake # with the third party directly before receiving the FD. If an implementation receives a second # attached FD after having already received one previously (e.g. both in a `thirdPartyHosted` # CapDescriptor and then later again when receiving the final capability directly from the # third party), the implementation should discard the later FD and stick with the original. At # present, there is no known reason why other capability types (e.g. `receiverHosted`) would want # to carry an attached FD, but we reserve the right to define a meaning for this in the future. # # Each file descriptor attached to the message must be used in no more than one CapDescriptor, # so that the receiver does not need to use dup() or refcounting to handle the possibility of # multiple capabilities using the same descriptor. If multiple CapDescriptors do point to the # same FD index, then the receiver can arbitrarily choose which capability ends up having the # FD attached. # # To mitigate DoS attacks, RPC implementations should limit the number of FDs they are willing to # receive in a single message to a small value. If a message happens to contain more than that, # the list is truncated. Moreover, in some cases, FD passing needs to be blocked entirely for # security or implementation reasons, in which case the list may be truncated to zero. Hence, # `attachedFd` might point past the end of the list, which the implementation should treat as if # no FD was attached at all. # # The type of this field was chosen to be UInt8 because Linux supports sending only a maximum # of 253 file descriptors in an SCM_RIGHTS message anyway, and CapDescriptor had two bytes of # padding left -- so after adding this, there is still one byte for a future feature. # Conveniently, this also means we're able to use 0xff as the default value, which will always # be out-of-range (of course, the implementation should explicitly enforce that 255 descriptors # cannot be sent at once, rather than relying on Linux to do so). } struct PromisedAnswer { # **(mostly level 1)** # # Specifies how to derive a promise from an unanswered question, by specifying the path of fields # to follow from the root of the eventual result struct to get to the desired capability. Used # to address method calls to a not-yet-returned capability or to pass such a capability as an # input to some other method call. # # Level 0 implementations must support `PromisedAnswer` only for the case where the answer is # to a `Bootstrap` message. In this case, `path` is always empty since `Bootstrap` always returns # a raw capability. questionId @0 :QuestionId; # ID of the question (in the sender's question table / receiver's answer table) whose answer is # expected to contain the capability. transform @1 :List(Op); # Operations / transformations to apply to the result in order to get the capability actually # being addressed. E.g. if the result is a struct and you want to call a method on a capability # pointed to by a field of the struct, you need a `getPointerField` op. struct Op { union { noop @0 :Void; # Does nothing. This member is mostly defined so that we can make `Op` a union even # though (as of this writing) only one real operation is defined. getPointerField @1 :UInt16; # Get a pointer field within a struct. The number is an index into the pointer section, NOT # a field ordinal, so that the receiver does not need to understand the schema. # TODO(someday): We could add: # - For lists, the ability to address every member of the list, or a slice of the list, the # result of which would be another list. This is useful for implementing the equivalent of # a SQL table join (not to be confused with the `Join` message type). # - Maybe some ability to test a union. # - Probably not a good idea: the ability to specify an arbitrary script to run on the # result. We could define a little stack-based language where `Op` specifies one # "instruction" or transformation to apply. Although this is not a good idea # (over-engineered), any narrower additions to `Op` should be designed as if this # were the eventual goal. } } } struct ThirdPartyCapDescriptor { # **(level 3)** # # Identifies a capability in a third-party vat that the sender wants the receiver to pick up. id @0 :ThirdPartyCapId; # Identifies the third-party host and the specific capability to accept from it. vineId @1 :ExportId; # A proxy for the third-party object exported by the sender. In CapTP terminology this is called # a "vine", because it is an indirect reference to the third-party object that snakes through the # sender vat. This serves two purposes: # # * Level 1 and 2 implementations that don't understand how to connect to a third party may # simply send calls to the vine. Such calls will be forwarded to the third-party by the # sender. # # * Level 3 implementations must release the vine only once they have successfully picked up the # object from the third party. This ensures that the capability is not released by the sender # prematurely. # # The sender will close the `Provide` request that it has sent to the third party as soon as # it receives either a `Call` or a `Release` message directed at the vine. } struct Exception { # **(level 0)** # # Describes an arbitrary error that prevented an operation (e.g. a call) from completing. # # Cap'n Proto exceptions always indicate that something went wrong. In other words, in a fantasy # world where everything always works as expected, no exceptions would ever be thrown. Clients # should only ever catch exceptions as a means to implement fault-tolerance, where "fault" can # mean: # - Bugs. # - Invalid input. # - Configuration errors. # - Network problems. # - Insufficient resources. # - Version skew (unimplemented functionality). # - Other logistical problems. # # Exceptions should NOT be used to flag application-specific conditions that a client is expected # to handle in an application-specific way. Put another way, in the Cap'n Proto world, # "checked exceptions" (where an interface explicitly defines the exceptions it throws and # clients are forced by the type system to handle those exceptions) do NOT make sense. reason @0 :Text; # Human-readable failure description. type @3 :Type; # The type of the error. The purpose of this enum is not to describe the error itself, but # rather to describe how the client might want to respond to the error. enum Type { failed @0; # A generic problem occurred, and it is believed that if the operation were repeated without # any change in the state of the world, the problem would occur again. # # A client might respond to this error by logging it for investigation by the developer and/or # displaying it to the user. overloaded @1; # The request was rejected due to a temporary lack of resources. # # Examples include: # - There's not enough CPU time to keep up with incoming requests, so some are rejected. # - The server ran out of RAM or disk space during the request. # - The operation timed out (took significantly longer than it should have). # # A client might respond to this error by scheduling to retry the operation much later. The # client should NOT retry again immediately since this would likely exacerbate the problem. disconnected @2; # The method failed because a connection to some necessary capability was lost. # # Examples include: # - The client introduced the server to a third-party capability, the connection to that third # party was subsequently lost, and then the client requested that the server use the dead # capability for something. # - The client previously requested that the server obtain a capability from some third party. # The server returned a capability to an object wrapping the third-party capability. Later, # the server's connection to the third party was lost. # - The capability has been revoked. Revocation does not necessarily mean that the client is # no longer authorized to use the capability; it is often used simply as a way to force the # client to repeat the setup process, perhaps to efficiently move them to a new back-end or # get them to recognize some other change that has occurred. # # A client should normally respond to this error by releasing all capabilities it is currently # holding related to the one it called and then re-creating them by restoring SturdyRefs and/or # repeating the method calls used to create them originally. In other words, disconnect and # start over. This should in turn cause the server to obtain a new copy of the capability that # it lost, thus making everything work. # # If the client receives another `disconnected` error in the process of rebuilding the # capability and retrying the call, it should treat this as an `overloaded` error: the network # is currently unreliable, possibly due to load or other temporary issues. unimplemented @3; # The server doesn't implement the requested method. If there is some other method that the # client could call (perhaps an older and/or slower interface), it should try that instead. # Otherwise, this should be treated like `failed`. } obsoleteIsCallersFault @1 :Bool; # OBSOLETE. Ignore. obsoleteDurability @2 :UInt16; # OBSOLETE. See `type` instead. trace @4 :Text; # Stack trace text from the remote server. The format is not specified. By default, # implementations do not provide stack traces; the application must explicitly enable them # when desired. } # ======================================================================================== # Network-specific Parameters # # Some parts of the Cap'n Proto RPC protocol are not specified here because different vat networks # may wish to use different approaches to solving them. For example, on the public internet, you # may want to authenticate vats using public-key cryptography, but on a local intranet with trusted # infrastructure, you may be happy to authenticate based on network address only, or some other # lightweight mechanism. # # To accommodate this, we specify several "parameter" types. Each type is defined here as an # alias for `AnyPointer`, but a specific network will want to define a specific set of types to use. # All vats in a vat network must agree on these parameters in order to be able to communicate. # Inter-network communication can be accomplished through "gateways" that perform translation # between the primitives used on each network; these gateways may need to be deeply stateful, # depending on the translations they perform. # # For interaction over the global internet between parties with no other prior arrangement, a # particular set of bindings for these types is defined elsewhere. (TODO(someday): Specify where # these common definitions live.) # # Another common network type is the two-party network, in which one of the parties typically # interacts with the outside world entirely through the other party. In such a connection between # Alice and Bob, all objects that exist on Bob's other networks appear to Alice as if they were # hosted by Bob himself, and similarly all objects on Alice's network (if she even has one) appear # to Bob as if they were hosted by Alice. This network type is interesting because from the point # of view of a simple application that communicates with only one other party via the two-party # protocol, there are no three-party interactions at all, and joins are unusually simple to # implement, so implementing at level 4 is barely more complicated than implementing at level 1. # Moreover, if you pair an app implementing the two-party network with a container that implements # some other network, the app can then participate on the container's network just as if it # implemented that network directly. The types used by the two-party network are defined in # `rpc-twoparty.capnp`. # # The things that we need to parameterize are: # - How to store capabilities long-term without holding a connection open (mostly level 2). # - How to authenticate vats in three-party introductions (level 3). # - How to implement `Join` (level 4). # # Persistent references # --------------------- # # **(mostly level 2)** # # We want to allow some capabilities to be stored long-term, even if a connection is lost and later # recreated. ExportId is a short-term identifier that is specific to a connection, so it doesn't # help here. We need a way to specify long-term identifiers, as well as a strategy for # reconnecting to a referenced capability later. # # Three-party interactions # ------------------------ # # **(level 3)** # # In cases where more than two vats are interacting, we have situations where VatA holds a # capability hosted by VatB and wants to send that capability to VatC. This can be accomplished # by VatA proxying requests on the new capability, but doing so has two big problems: # - It's inefficient, requiring an extra network hop. # - If VatC receives another capability to the same object from VatD, it is difficult for VatC to # detect that the two capabilities are really the same and to implement the E "join" operation, # which is necessary for certain four-or-more-party interactions, such as the escrow pattern. # See: http://www.erights.org/elib/equality/grant-matcher/index.html # # Instead, we want a way for VatC to form a direct, authenticated connection to VatB. # # Join # ---- # # **(level 4)** # # The `Join` message type and corresponding operation arranges for a direct connection to be formed # between the joiner and the host of the joined object, and this connection must be authenticated. # Thus, the details are network-dependent. using SturdyRef = AnyPointer; # **(level 2)** # # Identifies a persisted capability that can be restored in the future. How exactly a SturdyRef # is restored to a live object is specified along with the SturdyRef definition (i.e. not by # rpc.capnp). # # Generally a SturdyRef needs to specify three things: # - How to reach the vat that can restore the ref (e.g. a hostname or IP address). # - How to authenticate the vat after connecting (e.g. a public key fingerprint). # - The identity of a specific object hosted by the vat. Generally, this is an opaque pointer whose # format is defined by the specific vat -- the client has no need to inspect the object ID. # It is important that the object ID be unguessable if the object is not public (and objects # should almost never be public). # # The above are only suggestions. Some networks might work differently. For example, a private # network might employ a special restorer service whose sole purpose is to restore SturdyRefs. # In this case, the entire contents of SturdyRef might be opaque, because they are intended only # to be forwarded to the restorer service. using ProvisionId = AnyPointer; # **(level 3)** # # The information that must be sent in an `Accept` message to identify the object being accepted. # # In a network where each vat has a public/private key pair, this could simply be the public key # fingerprint of the provider vat along with a nonce matching the one in the `RecipientId` used # in the `Provide` message sent from that provider. using RecipientId = AnyPointer; # **(level 3)** # # The information that must be sent in a `Provide` message to identify the recipient of the # capability. # # In a network where each vat has a public/private key pair, this could simply be the public key # fingerprint of the recipient along with a nonce matching the one in the `ProvisionId`. # # As another example, when communicating between processes on the same machine over Unix sockets, # RecipientId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. # This file descriptor would be one end of a newly-created socketpair, with the other end having # been sent to the capability's recipient in ThirdPartyCapId. using ThirdPartyCapId = AnyPointer; # **(level 3)** # # The information needed to connect to a third party and accept a capability from it. # # In a network where each vat has a public/private key pair, this could be a combination of the # third party's public key fingerprint, hints on how to connect to the third party (e.g. an IP # address), and the nonce used in the corresponding `Provide` message's `RecipientId` as sent # to that third party (used to identify which capability to pick up). # # As another example, when communicating between processes on the same machine over Unix sockets, # ThirdPartyCapId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. # This file descriptor would be one end of a newly-created socketpair, with the other end having # been sent to the process hosting the capability in RecipientId. using JoinKeyPart = AnyPointer; # **(level 4)** # # A piece of a secret key. One piece is sent along each path that is expected to lead to the same # place. Once the pieces are combined, a direct connection may be formed between the sender and # the receiver, bypassing any men-in-the-middle along the paths. See the `Join` message type. # # The motivation for Joins is discussed under "Supporting Equality" in the "Unibus" protocol # sketch: http://www.erights.org/elib/distrib/captp/unibus.html # # In a network where each vat has a public/private key pair and each vat forms no more than one # connection to each other vat, Joins will rarely -- perhaps never -- be needed, as objects never # need to be transparently proxied and references to the same object sent over the same connection # have the same export ID. Thus, a successful join requires only checking that the two objects # come from the same connection and have the same ID, and then completes immediately. # # However, in networks where two vats may form more than one connection between each other, or # where proxying of objects occurs, joins are necessary. # # Typically, each JoinKeyPart would include a fixed-length data value such that all value parts # XOR'd together forms a shared secret that can be used to form an encrypted connection between # the joiner and the joined object's host. Each JoinKeyPart should also include an indication of # how many parts to expect and a hash of the shared secret (used to match up parts). using JoinResult = AnyPointer; # **(level 4)** # # Information returned as the result to a `Join` message, needed by the joiner in order to form a # direct connection to a joined object. This might simply be the address of the joined object's # host vat, since the `JoinKey` has already been communicated so the two vats already have a shared # secret to use to authenticate each other. # # The `JoinResult` should also contain information that can be used to detect when the Join # requests ended up reaching different objects, so that this situation can be detected easily. # This could be a simple matter of including a sequence number -- if the joiner receives two # `JoinResult`s with sequence number 0, then they must have come from different objects and the # whole join is a failure. # ======================================================================================== # Network interface sketch # # The interfaces below are meant to be pseudo-code to illustrate how the details of a particular # vat network might be abstracted away. They are written like Cap'n Proto interfaces, but in # practice you'd probably define these interfaces manually in the target programming language. A # Cap'n Proto RPC implementation should be able to use these interfaces without knowing the # definitions of the various network-specific parameters defined above. # interface VatNetwork { # # Represents a vat network, with the ability to connect to particular vats and receive # # connections from vats. # # # # Note that methods returning a `Connection` may return a pre-existing `Connection`, and the # # caller is expected to find and share state with existing users of the connection. # # # Level 0 features ----------------------------------------------- # # connect(vatId :VatId) :Connection; # # Connect to the given vat. The transport should return a promise that does not # # resolve until authentication has completed, but allows messages to be pipelined in before # # that; the transport either queues these messages until authenticated, or sends them encrypted # # such that only the authentic vat would be able to decrypt them. The latter approach avoids a # # round trip for authentication. # # accept() :Connection; # # Wait for the next incoming connection and return it. Only connections formed by # # connect() are returned by this method. # # # Level 4 features ----------------------------------------------- # # newJoiner(count :UInt32) :NewJoinerResponse; # # Prepare a new Join operation, which will eventually lead to forming a new direct connection # # to the host of the joined capability. `count` is the number of capabilities to join. # # struct NewJoinerResponse { # joinKeyParts :List(JoinKeyPart); # # Key parts to send in Join messages to each capability. # # joiner :Joiner; # # Used to establish the final connection. # } # # interface Joiner { # addJoinResult(result :JoinResult) :Void; # # Add a JoinResult received in response to one of the `Join` messages. All `JoinResult`s # # returned from all paths must be added before trying to connect. # # connect() :ConnectionAndProvisionId; # # Try to form a connection to the joined capability's host, verifying that it has received # # all of the JoinKeyParts. Once the connection is formed, the caller should send an `Accept` # # message on it with the specified `ProvisionId` in order to receive the final capability. # } # # acceptConnectionFromJoiner(parts :List(JoinKeyPart), paths :List(VatPath)) # :ConnectionAndProvisionId; # # Called on a joined capability's host to receive the connection from the joiner, once all # # key parts have arrived. The caller should expect to receive an `Accept` message over the # # connection with the given ProvisionId. # } # # interface Connection { # # Level 0 features ----------------------------------------------- # # send(message :Message) :Void; # # Send the message. Returns successfully when the message (and all preceding messages) has # # been acknowledged by the recipient. # # receive() :Message; # # Receive the next message, and acknowledges receipt to the sender. Messages are received in # # the order in which they are sent. # # # Level 3 features ----------------------------------------------- # # introduceTo(recipient :Connection) :IntroductionInfo; # # Call before starting a three-way introduction, assuming a `Provide` message is to be sent on # # this connection and a `ThirdPartyCapId` is to be sent to `recipient`. # # struct IntroductionInfo { # sendToRecipient :ThirdPartyCapId; # sendToTarget :RecipientId; # } # # connectToIntroduced(capId :ThirdPartyCapId) :ConnectionAndProvisionId; # # Given a ThirdPartyCapId received over this connection, connect to the third party. The # # caller should then send an `Accept` message over the new connection. # # acceptIntroducedConnection(recipientId :RecipientId) :Connection; # # Given a RecipientId received in a `Provide` message on this `Connection`, wait for the # # recipient to connect, and return the connection formed. Usually, the first message received # # on the new connection will be an `Accept` message. # } # # struct ConnectionAndProvisionId { # # **(level 3)** # # connection :Connection; # # Connection on which to issue `Accept` message. # # provision :ProvisionId; # # `ProvisionId` to send in the `Accept` message. # } capnproto-c++-1.1.0/src/capnp/endian-reverse-test.c++0000644000175000017500000000651214527152321023016 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #if !_MSC_VER // (MSVC targets only little-endian platforms and so we haven't implemented any byte swapping // intrinsics for it. So, this test would fail there.) // Test that the code for the opposite endianness of our CPU works. E.g. on x86 this will test // the bswap-based code. #define CAPNP_REVERSE_ENDIAN 1 #include "endian.h" #include namespace capnp { namespace _ { // private namespace { TEST(EndianReverse, Byte) { byte bytes[] = {123, 45, 67, 89}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(123, vals[0].get()); EXPECT_EQ(45, vals[1].get()); EXPECT_EQ(67, vals[2].get()); EXPECT_EQ(89, vals[3].get()); vals[0].set(21); vals[1].set(43); vals[2].set(65); vals[3].set(87); EXPECT_EQ(21, bytes[0]); EXPECT_EQ(43, bytes[1]); EXPECT_EQ(65, bytes[2]); EXPECT_EQ(87, bytes[3]); } TEST(EndianReverse, TwoBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0x1234, vals[0].get()); EXPECT_EQ(0x5678, vals[1].get()); vals[0].set(0x2345); vals[1].set(0x6789); EXPECT_EQ(0x23, bytes[0]); EXPECT_EQ(0x45, bytes[1]); EXPECT_EQ(0x67, bytes[2]); EXPECT_EQ(0x89, bytes[3]); } TEST(EndianReverse, FourBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0x12345678u, vals[0].get()); vals[0].set(0x23456789); EXPECT_EQ(0x23, bytes[0]); EXPECT_EQ(0x45, bytes[1]); EXPECT_EQ(0x67, bytes[2]); EXPECT_EQ(0x89, bytes[3]); } TEST(EndianReverse, EightBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0x123456789abcdef0ull, vals[0].get()); vals[0].set(0x23456789abcdef01ull); EXPECT_EQ(0x23, bytes[0]); EXPECT_EQ(0x45, bytes[1]); EXPECT_EQ(0x67, bytes[2]); EXPECT_EQ(0x89, bytes[3]); EXPECT_EQ(0xab, bytes[4]); EXPECT_EQ(0xcd, bytes[5]); EXPECT_EQ(0xef, bytes[6]); EXPECT_EQ(0x01, bytes[7]); } } // namespace } // namespace _ (private) } // namespace capnp #endif // !_MSC_VER capnproto-c++-1.1.0/src/capnp/membrane.c++0000644000175000017500000005454214712011043020715 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "membrane.h" #include namespace capnp { namespace { static const char DUMMY = 0; static constexpr const void* MEMBRANE_BRAND = &DUMMY; kj::Own membrane(kj::Own inner, MembranePolicy& policy, bool reverse); class MembraneCapTableReader final: public _::CapTableReader { public: MembraneCapTableReader(MembranePolicy& policy, bool reverse) : policy(policy), reverse(reverse) {} AnyPointer::Reader imbue(AnyPointer::Reader reader) { return AnyPointer::Reader(imbue( _::PointerHelpers::getInternalReader(kj::mv(reader)))); } _::PointerReader imbue(_::PointerReader reader) { KJ_REQUIRE(inner == nullptr, "can only call this once"); inner = reader.getCapTable(); return reader.imbue(this); } _::StructReader imbue(_::StructReader reader) { KJ_REQUIRE(inner == nullptr, "can only call this once"); inner = reader.getCapTable(); return reader.imbue(this); } _::ListReader imbue(_::ListReader reader) { KJ_REQUIRE(inner == nullptr, "can only call this once"); inner = reader.getCapTable(); return reader.imbue(this); } kj::Maybe> extractCap(uint index) override { // The underlying message is inside the membrane, and we're pulling a cap out of it. Therefore, // we want to wrap the extracted capability in the membrane. return inner->extractCap(index).map([this](kj::Own&& cap) { return membrane(kj::mv(cap), policy, reverse); }); } private: _::CapTableReader* inner = nullptr; MembranePolicy& policy; bool reverse; }; class MembraneCapTableBuilder final: public _::CapTableBuilder { public: MembraneCapTableBuilder(MembranePolicy& policy, bool reverse) : policy(policy), reverse(reverse) {} AnyPointer::Builder imbue(AnyPointer::Builder builder) { KJ_REQUIRE(inner == nullptr, "can only call this once"); auto pointerBuilder = _::PointerHelpers::getInternalBuilder(kj::mv(builder)); inner = pointerBuilder.getCapTable(); return AnyPointer::Builder(pointerBuilder.imbue(this)); } AnyPointer::Builder unimbue(AnyPointer::Builder builder) { auto pointerBuilder = _::PointerHelpers::getInternalBuilder(kj::mv(builder)); KJ_REQUIRE(pointerBuilder.getCapTable() == this); return AnyPointer::Builder(pointerBuilder.imbue(inner)); } kj::Maybe> extractCap(uint index) override { // The underlying message is inside the membrane, and we're pulling a cap out of it. Therefore, // we want to wrap the extracted capability in the membrane. return inner->extractCap(index).map([this](kj::Own&& cap) { return membrane(kj::mv(cap), policy, reverse); }); } uint injectCap(kj::Own&& cap) override { // The underlying message is inside the membrane, and we're inserting a cap from outside into // it. Therefore we want to add a reverse membrane. return inner->injectCap(membrane(kj::mv(cap), policy, !reverse)); } void dropCap(uint index) override { inner->dropCap(index); } private: _::CapTableBuilder* inner = nullptr; MembranePolicy& policy; bool reverse; }; class MembranePipelineHook final: public PipelineHook, public kj::Refcounted { public: MembranePipelineHook( kj::Own&& inner, kj::Own&& policy, bool reverse) : inner(kj::mv(inner)), policy(kj::mv(policy)), reverse(reverse) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { return membrane(inner->getPipelinedCap(ops), *policy, reverse); } kj::Own getPipelinedCap(kj::Array&& ops) override { return membrane(inner->getPipelinedCap(kj::mv(ops)), *policy, reverse); } private: kj::Own inner; kj::Own policy; bool reverse; }; class MembraneResponseHook final: public ResponseHook { public: MembraneResponseHook( kj::Own&& inner, kj::Own&& policy, bool reverse) : inner(kj::mv(inner)), policy(kj::mv(policy)), capTable(*this->policy, reverse) {} AnyPointer::Reader imbue(AnyPointer::Reader reader) { return capTable.imbue(reader); } private: kj::Own inner; kj::Own policy; MembraneCapTableReader capTable; }; class MembraneRequestHook final: public RequestHook { public: MembraneRequestHook(kj::Own&& inner, kj::Own&& policy, bool reverse) : inner(kj::mv(inner)), policy(kj::mv(policy)), reverse(reverse), capTable(*this->policy, reverse) {} static Request wrap( Request&& inner, MembranePolicy& policy, bool reverse) { AnyPointer::Builder builder = inner; auto innerHook = RequestHook::from(kj::mv(inner)); if (innerHook->getBrand() == MEMBRANE_BRAND) { auto& otherMembrane = kj::downcast(*innerHook); if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { // Request that passed across the membrane one way is now passing back the other way. // Unwrap it rather than double-wrap it. builder = otherMembrane.capTable.unimbue(builder); return { builder, kj::mv(otherMembrane.inner) }; } } auto newHook = kj::heap(kj::mv(innerHook), policy.addRef(), reverse); builder = newHook->capTable.imbue(builder); return { builder, kj::mv(newHook) }; } static kj::Own wrap( kj::Own&& inner, MembranePolicy& policy, bool reverse) { if (inner->getBrand() == MEMBRANE_BRAND) { auto& otherMembrane = kj::downcast(*inner); if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { // Request that passed across the membrane one way is now passing back the other way. // Unwrap it rather than double-wrap it. return kj::mv(otherMembrane.inner); } } return kj::heap(kj::mv(inner), policy.addRef(), reverse); } RemotePromise send() override { auto promise = inner->send(); auto newPipeline = AnyPointer::Pipeline(kj::refcounted( PipelineHook::from(kj::mv(promise)), policy->addRef(), reverse)); auto onRevoked = policy->onRevoked(); bool reverse = this->reverse; // for capture auto newPromise = promise.then( [reverse,policy=kj::mv(policy)](Response&& response) mutable { AnyPointer::Reader reader = response; auto newRespHook = kj::heap( ResponseHook::from(kj::mv(response)), policy->addRef(), reverse); reader = newRespHook->imbue(reader); return Response(reader, kj::mv(newRespHook)); }); KJ_IF_MAYBE(r, kj::mv(onRevoked)) { newPromise = newPromise.exclusiveJoin(r->then([]() -> Response { KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); })); } return RemotePromise(kj::mv(newPromise), kj::mv(newPipeline)); } kj::Promise sendStreaming() override { auto promise = inner->sendStreaming(); KJ_IF_MAYBE(r, policy->onRevoked()) { promise = promise.exclusiveJoin(r->then([]() { KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); })); } return promise; } AnyPointer::Pipeline sendForPipeline() override { return AnyPointer::Pipeline(kj::refcounted( PipelineHook::from(inner->sendForPipeline()), policy->addRef(), reverse)); } const void* getBrand() override { return MEMBRANE_BRAND; } private: kj::Own inner; kj::Own policy; bool reverse; MembraneCapTableBuilder capTable; }; class MembraneCallContextHook final: public CallContextHook, public kj::Refcounted { public: MembraneCallContextHook(kj::Own&& inner, kj::Own&& policy, bool reverse) : inner(kj::mv(inner)), policy(kj::mv(policy)), reverse(reverse), paramsCapTable(*this->policy, reverse), resultsCapTable(*this->policy, reverse) {} AnyPointer::Reader getParams() override { KJ_REQUIRE(!releasedParams); KJ_IF_MAYBE(p, params) { return *p; } else { auto result = paramsCapTable.imbue(inner->getParams()); params = result; return result; } } void releaseParams() override { // Note that releaseParams() is idempotent -- it can be called multiple times. releasedParams = true; inner->releaseParams(); } AnyPointer::Builder getResults(kj::Maybe sizeHint) override { KJ_IF_MAYBE(r, results) { return *r; } else { auto result = resultsCapTable.imbue(inner->getResults(sizeHint)); results = result; return result; } } void setPipeline(kj::Own&& pipeline) override { inner->setPipeline(kj::refcounted( kj::mv(pipeline), policy->addRef(), !reverse)); } kj::Promise tailCall(kj::Own&& request) override { return inner->tailCall(MembraneRequestHook::wrap(kj::mv(request), *policy, !reverse)); } kj::Promise onTailCall() override { return inner->onTailCall().then([this](AnyPointer::Pipeline&& innerPipeline) { return AnyPointer::Pipeline(kj::refcounted( PipelineHook::from(kj::mv(innerPipeline)), policy->addRef(), reverse)); }); } ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own&& request) override { auto pair = inner->directTailCall( MembraneRequestHook::wrap(kj::mv(request), *policy, !reverse)); return { kj::mv(pair.promise), kj::refcounted(kj::mv(pair.pipeline), policy->addRef(), reverse) }; } kj::Own addRef() override { return kj::addRef(*this); } private: kj::Own inner; kj::Own policy; bool reverse; MembraneCapTableReader paramsCapTable; kj::Maybe params; bool releasedParams = false; MembraneCapTableBuilder resultsCapTable; kj::Maybe results; }; } // namespace class MembraneHook final: public ClientHook, public kj::Refcounted { public: MembraneHook(kj::Own&& inner, kj::Own&& policyParam, bool reverse) : inner(kj::mv(inner)), policy(kj::mv(policyParam)), reverse(reverse) { KJ_IF_MAYBE(r, policy->onRevoked()) { revocationTask = r->eagerlyEvaluate([this](kj::Exception&& exception) { this->inner = newBrokenCap(kj::mv(exception)); }); } } ~MembraneHook() noexcept(false) { auto& map = reverse ? policy->reverseWrappers : policy->wrappers; map.erase(inner.get()); } static kj::Own wrap(ClientHook& cap, MembranePolicy& policy, bool reverse) { if (cap.getBrand() == MEMBRANE_BRAND) { auto& otherMembrane = kj::downcast(cap); auto& rootPolicy = policy.rootPolicy(); if (&otherMembrane.policy->rootPolicy() == &rootPolicy && otherMembrane.reverse == !reverse) { // Capability that passed across the membrane one way is now passing back the other way. // Unwrap it rather than double-wrap it. Capability::Client unwrapped(otherMembrane.inner->addRef()); return ClientHook::from( reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy) : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy)); } } auto& map = reverse ? policy.reverseWrappers : policy.wrappers; ClientHook*& slot = map.findOrCreate(&cap, [&]() -> kj::Decay::Entry { return { &cap, nullptr }; }); if (slot == nullptr) { auto result = ClientHook::from( reverse ? policy.importExternal(Capability::Client(cap.addRef())) : policy.exportInternal(Capability::Client(cap.addRef()))); slot = result; return result; } else { return slot->addRef(); } } static kj::Own wrap(kj::Own cap, MembranePolicy& policy, bool reverse) { if (cap->getBrand() == MEMBRANE_BRAND) { auto& otherMembrane = kj::downcast(*cap); auto& rootPolicy = policy.rootPolicy(); if (&otherMembrane.policy->rootPolicy() == &rootPolicy && otherMembrane.reverse == !reverse) { // Capability that passed across the membrane one way is now passing back the other way. // Unwrap it rather than double-wrap it. Capability::Client unwrapped(otherMembrane.inner->addRef()); return ClientHook::from( reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy) : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy)); } } auto& map = reverse ? policy.reverseWrappers : policy.wrappers; ClientHook*& slot = map.findOrCreate(cap.get(), [&]() -> kj::Decay::Entry { return { cap.get(), nullptr }; }); if (slot == nullptr) { auto result = ClientHook::from( reverse ? policy.importExternal(Capability::Client(kj::mv(cap))) : policy.exportInternal(Capability::Client(kj::mv(cap)))); slot = result; return result; } else { return slot->addRef(); } } Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { KJ_IF_MAYBE(r, resolved) { return r->get()->newCall(interfaceId, methodId, sizeHint, hints); } auto redirect = reverse ? policy->outboundCall(interfaceId, methodId, Capability::Client(inner->addRef())) : policy->inboundCall(interfaceId, methodId, Capability::Client(inner->addRef())); KJ_IF_MAYBE(r, redirect) { if (policy->shouldResolveBeforeRedirecting()) { // The policy says that *if* this capability points into the membrane, then we want to // redirect the call. However, if this capability is a promise, then it could resolve to // something outside the membrane later. We have to wait before we actually redirect, // otherwise behavior will differ depending on whether the promise is resolved. KJ_IF_MAYBE(p, whenMoreResolved()) { return newLocalPromiseClient(p->attach(addRef())) ->newCall(interfaceId, methodId, sizeHint, hints); } } return ClientHook::from(kj::mv(*r))->newCall(interfaceId, methodId, sizeHint, hints); } else { // For pass-through calls, we don't worry about promises, because if the capability resolves // to something outside the membrane, then the call will pass back out of the membrane too. return MembraneRequestHook::wrap( inner->newCall(interfaceId, methodId, sizeHint, hints), *policy, reverse); } } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { KJ_IF_MAYBE(r, resolved) { return r->get()->call(interfaceId, methodId, kj::mv(context), hints); } auto redirect = reverse ? policy->outboundCall(interfaceId, methodId, Capability::Client(inner->addRef())) : policy->inboundCall(interfaceId, methodId, Capability::Client(inner->addRef())); KJ_IF_MAYBE(r, redirect) { if (policy->shouldResolveBeforeRedirecting()) { // The policy says that *if* this capability points into the membrane, then we want to // redirect the call. However, if this capability is a promise, then it could resolve to // something outside the membrane later. We have to wait before we actually redirect, // otherwise behavior will differ depending on whether the promise is resolved. KJ_IF_MAYBE(p, whenMoreResolved()) { return newLocalPromiseClient(p->attach(addRef())) ->call(interfaceId, methodId, kj::mv(context), hints); } } return ClientHook::from(kj::mv(*r))->call(interfaceId, methodId, kj::mv(context), hints); } else { // !reverse because calls to the CallContext go in the opposite direction. auto result = inner->call(interfaceId, methodId, kj::refcounted(kj::mv(context), policy->addRef(), !reverse), hints); if (hints.onlyPromisePipeline) { // Just in case the called capability returned a valid promise, replace it here. result.promise = kj::NEVER_DONE; } else KJ_IF_MAYBE(r, policy->onRevoked()) { result.promise = result.promise.exclusiveJoin(kj::mv(*r)); } return { kj::mv(result.promise), kj::refcounted(kj::mv(result.pipeline), policy->addRef(), reverse) }; } } kj::Maybe getResolved() override { KJ_IF_MAYBE(r, resolved) { return **r; } KJ_IF_MAYBE(newInner, inner->getResolved()) { kj::Own newResolved = wrap(*newInner, *policy, reverse); ClientHook& result = *newResolved; resolved = kj::mv(newResolved); return result; } else { return nullptr; } } kj::Maybe>> whenMoreResolved() override { KJ_IF_MAYBE(r, resolved) { return kj::Promise>(r->get()->addRef()); } KJ_IF_MAYBE(promise, inner->whenMoreResolved()) { KJ_IF_MAYBE(r, policy->onRevoked()) { *promise = promise->exclusiveJoin(r->then([]() -> kj::Own { KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); })); } return promise->then([this](kj::Own&& newInner) { // There's a chance resolved was set by getResolved() or a concurrent whenMoreResolved() // while we yielded the event loop. If the inner ClientHook is maintaining the contract, // then resolved would already be set to newInner after wrapping in a MembraneHook. KJ_IF_MAYBE(r, resolved) { return (*r)->addRef(); } else { return resolved.emplace(wrap(*newInner, *policy, reverse))->addRef(); } }); } else { return nullptr; } } kj::Own addRef() override { return kj::addRef(*this); } const void* getBrand() override { return MEMBRANE_BRAND; } kj::Maybe getFd() override { KJ_IF_MAYBE(f, inner->getFd()) { if (policy->allowFdPassthrough()) { return *f; } } return nullptr; } private: kj::Own inner; kj::Own policy; bool reverse; kj::Maybe> resolved; kj::Promise revocationTask = nullptr; }; namespace { kj::Own membrane(kj::Own inner, MembranePolicy& policy, bool reverse) { return MembraneHook::wrap(kj::mv(inner), policy, reverse); } } // namespace Capability::Client MembranePolicy::importExternal(Capability::Client external) { return Capability::Client(kj::refcounted( ClientHook::from(kj::mv(external)), addRef(), true)); } Capability::Client MembranePolicy::exportInternal(Capability::Client internal) { return Capability::Client(kj::refcounted( ClientHook::from(kj::mv(internal)), addRef(), false)); } Capability::Client MembranePolicy::importInternal( Capability::Client internal, MembranePolicy& exportPolicy, MembranePolicy& importPolicy) { return kj::mv(internal); } Capability::Client MembranePolicy::exportExternal( Capability::Client external, MembranePolicy& importPolicy, MembranePolicy& exportPolicy) { return kj::mv(external); } Capability::Client membrane(Capability::Client inner, kj::Own policy) { return Capability::Client(membrane( ClientHook::from(kj::mv(inner)), *policy, false)); } Capability::Client reverseMembrane(Capability::Client inner, kj::Own policy) { return Capability::Client(membrane( ClientHook::from(kj::mv(inner)), *policy, true)); } namespace _ { // private _::OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to, kj::Own policy, bool reverse) { MembraneCapTableReader capTable(*policy, reverse); return _::OrphanBuilder::copy( OrphanageInternal::getArena(to), OrphanageInternal::getCapTable(to), capTable.imbue(from)); } _::OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to, kj::Own policy, bool reverse) { MembraneCapTableReader capTable(*policy, reverse); return _::OrphanBuilder::copy( OrphanageInternal::getArena(to), OrphanageInternal::getCapTable(to), capTable.imbue(from)); } _::OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to, kj::Own policy, bool reverse) { MembraneCapTableReader capTable(*policy, reverse); return _::OrphanBuilder::copy( OrphanageInternal::getArena(to), OrphanageInternal::getCapTable(to), capTable.imbue(from)); } } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/endian-test.c++0000644000175000017500000000604214527152321021343 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "endian.h" #include namespace capnp { namespace _ { // private namespace { #if CAPNP_DISABLE_ENDIAN_DETECTION #define Endian EndianUnoptimized #endif TEST(Endian, Byte) { byte bytes[] = {123, 45, 67, 89}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(123, vals[0].get()); EXPECT_EQ(45, vals[1].get()); EXPECT_EQ(67, vals[2].get()); EXPECT_EQ(89, vals[3].get()); vals[0].set(21); vals[1].set(43); vals[2].set(65); vals[3].set(87); EXPECT_EQ(21, bytes[0]); EXPECT_EQ(43, bytes[1]); EXPECT_EQ(65, bytes[2]); EXPECT_EQ(87, bytes[3]); } TEST(Endian, TwoBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0x3412, vals[0].get()); EXPECT_EQ(0x7856, vals[1].get()); vals[0].set(0x2345); vals[1].set(0x6789); EXPECT_EQ(0x45, bytes[0]); EXPECT_EQ(0x23, bytes[1]); EXPECT_EQ(0x89, bytes[2]); EXPECT_EQ(0x67, bytes[3]); } TEST(Endian, FourBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0x78563412u, vals[0].get()); vals[0].set(0x23456789); EXPECT_EQ(0x89, bytes[0]); EXPECT_EQ(0x67, bytes[1]); EXPECT_EQ(0x45, bytes[2]); EXPECT_EQ(0x23, bytes[3]); } TEST(Endian, EightBytes) { byte bytes[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; WireValue* vals = reinterpret_cast*>(bytes); EXPECT_EQ(0xf0debc9a78563412, vals[0].get()); vals[0].set(0x23456789abcdef01); EXPECT_EQ(0x01, bytes[0]); EXPECT_EQ(0xef, bytes[1]); EXPECT_EQ(0xcd, bytes[2]); EXPECT_EQ(0xab, bytes[3]); EXPECT_EQ(0x89, bytes[4]); EXPECT_EQ(0x67, bytes[5]); EXPECT_EQ(0x45, bytes[6]); EXPECT_EQ(0x23, bytes[7]); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/endian.h0000644000175000017500000002207614527152321020252 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "common.h" #include #include // memcpy CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private // WireValue // // Wraps a primitive value as it appears on the wire. Namely, values are little-endian on the // wire, because little-endian is the most common endianness in modern CPUs. // // Note: In general, code that depends cares about byte ordering is bad. See: // http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html // Cap'n Proto is special because it is essentially doing compiler-like things, fussing over // allocation and layout of memory, in order to squeeze out every last drop of performance. #if _MSC_VER // Assume Windows is little-endian. // // TODO(msvc): This is ugly. Maybe refactor later checks to be based on CAPNP_BYTE_ORDER or // CAPNP_SWAP_BYTES or something, and define that in turn based on _MSC_VER or the GCC // intrinsics. #ifndef __ORDER_BIG_ENDIAN__ #define __ORDER_BIG_ENDIAN__ 4321 #endif #ifndef __ORDER_LITTLE_ENDIAN__ #define __ORDER_LITTLE_ENDIAN__ 1234 #endif #ifndef __BYTE_ORDER__ #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ #endif #endif #if CAPNP_REVERSE_ENDIAN #define CAPNP_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__ #define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__ #else #define CAPNP_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__ #define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__ #endif #if defined(__BYTE_ORDER__) && \ __BYTE_ORDER__ == CAPNP_WIRE_BYTE_ORDER && \ !CAPNP_DISABLE_ENDIAN_DETECTION // CPU is little-endian. We can just read/write the memory directly. template class DirectWireValue { public: KJ_ALWAYS_INLINE(T get() const) { return value; } KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } private: T value; }; template using WireValue = DirectWireValue; // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are // linked together, we define each implementation with a different name and define an alias to the // one we want to use. #elif defined(__BYTE_ORDER__) && \ __BYTE_ORDER__ == CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER && \ defined(__GNUC__) && !CAPNP_DISABLE_ENDIAN_DETECTION // Big-endian, but GCC's __builtin_bswap() is available. // TODO(perf): Use dedicated instructions to read little-endian data on big-endian CPUs that have // them. // TODO(perf): Verify that this code optimizes reasonably. In particular, ensure that the // compiler optimizes away the memcpy()s and keeps everything in registers. template class SwappingWireValue; template class SwappingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { return value; } KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } private: T value; }; template class SwappingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { // Not all platforms have __builtin_bswap16() for some reason. In particular, it is missing // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64). uint16_t swapped = (value << 8) | (value >> 8); T result; memcpy(&result, &swapped, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint16_t raw; memcpy(&raw, &newValue, sizeof(T)); // Not all platforms have __builtin_bswap16() for some reason. In particular, it is missing // on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64). value = (raw << 8) | (raw >> 8); } private: uint16_t value; }; template class SwappingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { uint32_t swapped = __builtin_bswap32(value); T result; memcpy(&result, &swapped, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint32_t raw; memcpy(&raw, &newValue, sizeof(T)); value = __builtin_bswap32(raw); } private: uint32_t value; }; template class SwappingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { uint64_t swapped = __builtin_bswap64(value); T result; memcpy(&result, &swapped, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint64_t raw; memcpy(&raw, &newValue, sizeof(T)); value = __builtin_bswap64(raw); } private: uint64_t value; }; template using WireValue = SwappingWireValue; // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are // linked together, we define each implementation with a different name and define an alias to the // one we want to use. #else // Unknown endianness. Fall back to bit shifts. #if !CAPNP_DISABLE_ENDIAN_DETECTION #if _MSC_VER #pragma message("Couldn't detect endianness of your platform. Using unoptimized fallback implementation.") #pragma message("Consider changing this code to detect your platform and send us a patch!") #else #warning "Couldn't detect endianness of your platform. Using unoptimized fallback implementation." #warning "Consider changing this code to detect your platform and send us a patch!" #endif #endif // !CAPNP_DISABLE_ENDIAN_DETECTION template class ShiftingWireValue; template class ShiftingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { return value; } KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; } private: T value; }; template class ShiftingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { uint16_t raw = (static_cast(bytes[0]) ) | (static_cast(bytes[1]) << 8); T result; memcpy(&result, &raw, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint16_t raw; memcpy(&raw, &newValue, sizeof(T)); bytes[0] = raw; bytes[1] = raw >> 8; } private: union { byte bytes[2]; uint16_t align; }; }; template class ShiftingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { uint32_t raw = (static_cast(bytes[0]) ) | (static_cast(bytes[1]) << 8) | (static_cast(bytes[2]) << 16) | (static_cast(bytes[3]) << 24); T result; memcpy(&result, &raw, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint32_t raw; memcpy(&raw, &newValue, sizeof(T)); bytes[0] = raw; bytes[1] = raw >> 8; bytes[2] = raw >> 16; bytes[3] = raw >> 24; } private: union { byte bytes[4]; uint32_t align; }; }; template class ShiftingWireValue { public: KJ_ALWAYS_INLINE(T get() const) { uint64_t raw = (static_cast(bytes[0]) ) | (static_cast(bytes[1]) << 8) | (static_cast(bytes[2]) << 16) | (static_cast(bytes[3]) << 24) | (static_cast(bytes[4]) << 32) | (static_cast(bytes[5]) << 40) | (static_cast(bytes[6]) << 48) | (static_cast(bytes[7]) << 56); T result; memcpy(&result, &raw, sizeof(T)); return result; } KJ_ALWAYS_INLINE(void set(T newValue)) { uint64_t raw; memcpy(&raw, &newValue, sizeof(T)); bytes[0] = raw; bytes[1] = raw >> 8; bytes[2] = raw >> 16; bytes[3] = raw >> 24; bytes[4] = raw >> 32; bytes[5] = raw >> 40; bytes[6] = raw >> 48; bytes[7] = raw >> 56; } private: union { byte bytes[8]; uint64_t align; }; }; template using WireValue = ShiftingWireValue; // To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are // linked together, we define each implementation with a different name and define an alias to the // one we want to use. #endif } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/layout.c++0000644000175000017500000045735114712011043020451 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "layout.h" #include #include "arena.h" #include #include #if !CAPNP_LITE #include "capability.h" #endif // !CAPNP_LITE namespace capnp { namespace _ { // private #if !CAPNP_LITE static BrokenCapFactory* globalBrokenCapFactory = nullptr; // Horrible hack: We need to be able to construct broken caps without any capability context, // but we can't have a link-time dependency on libcapnp-rpc. void setGlobalBrokenCapFactoryForLayoutCpp(BrokenCapFactory& factory) { // Called from capability.c++ when the capability API is used, to make sure that layout.c++ // is ready for it. May be called multiple times but always with the same value. #if __GNUC__ || defined(__clang__) __atomic_store_n(&globalBrokenCapFactory, &factory, __ATOMIC_RELAXED); #elif _MSC_VER *static_cast(&globalBrokenCapFactory) = &factory; #else #error "Platform not supported" #endif } static BrokenCapFactory* readGlobalBrokenCapFactoryForLayoutCpp() { #if __GNUC__ || defined(__clang__) // Thread-sanitizer doesn't have the right information to know this is safe without doing an // atomic read. https://groups.google.com/g/capnproto/c/634juhn5ap0/m/pyRiwWl1AAAJ return __atomic_load_n(&globalBrokenCapFactory, __ATOMIC_RELAXED); #else return globalBrokenCapFactory; #endif } } // namespace _ (private) const uint ClientHook::NULL_CAPABILITY_BRAND = 0; const uint ClientHook::BROKEN_CAPABILITY_BRAND = 0; // Defined here rather than capability.c++ so that we can safely call isNull() in this file. namespace _ { // private #endif // !CAPNP_LITE #if CAPNP_DEBUG_TYPES #define G(n) bounded() #else #define G(n) n #endif // ======================================================================================= #if __GNUC__ >= 8 && !__clang__ // GCC 8 introduced a warning which complains whenever we try to memset() or memcpy() a // WirePointer, because we deleted the regular copy constructor / assignment operator. Weirdly, if // I remove those deletions, GCC *still* complains that WirePointer is non-trivial. I don't // understand why -- maybe because WireValue has private members? We don't want to make WireValue's // member public, but memset() and memcpy() on it are certainly valid and desirable, so we'll just // have to disable the warning I guess. #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif struct WirePointer { // A pointer, in exactly the format in which it appears on the wire. // Copying and moving is not allowed because the offset would become wrong. WirePointer(const WirePointer& other) = delete; WirePointer(WirePointer&& other) = delete; WirePointer& operator=(const WirePointer& other) = delete; WirePointer& operator=(WirePointer&& other) = delete; // ----------------------------------------------------------------- // Common part of all pointers: kind + offset // // Actually this is not terribly common. The "offset" could actually be different things // depending on the context: // - For a regular (e.g. struct/list) pointer, a signed word offset from the word immediately // following the pointer pointer. (The off-by-one means the offset is more often zero, saving // bytes on the wire when packed.) // - For an inline composite list tag (not really a pointer, but structured similarly), an // element count. // - For a FAR pointer, an unsigned offset into the target segment. // - For a FAR landing pad, zero indicates that the target value immediately follows the pad while // 1 indicates that the pad is followed by another FAR pointer that actually points at the // value. enum Kind { STRUCT = 0, // Reference points at / describes a struct. LIST = 1, // Reference points at / describes a list. FAR = 2, // Reference is a "far pointer", which points at data located in a different segment. The // eventual target is one of the other kinds. OTHER = 3 // Reference has type "other". If the next 30 bits are all zero (i.e. the lower 32 bits contain // only the kind OTHER) then the pointer is a capability. All other values are reserved. }; WireValue offsetAndKind; KJ_ALWAYS_INLINE(Kind kind() const) { return static_cast(offsetAndKind.get() & 3); } KJ_ALWAYS_INLINE(bool isPositional() const) { return (offsetAndKind.get() & 2) == 0; // match STRUCT and LIST but not FAR or OTHER } KJ_ALWAYS_INLINE(bool isCapability() const) { return offsetAndKind.get() == OTHER; } KJ_ALWAYS_INLINE(word* target()) { return reinterpret_cast(this) + 1 + (static_cast(offsetAndKind.get()) >> 2); } KJ_ALWAYS_INLINE(const word* target(SegmentReader* segment) const) { if (segment == nullptr) { return reinterpret_cast(this + 1) + (static_cast(offsetAndKind.get()) >> 2); } else { return segment->checkOffset(reinterpret_cast(this + 1), static_cast(offsetAndKind.get()) >> 2); } } KJ_ALWAYS_INLINE(void setKindAndTarget(Kind kind, word* target, SegmentBuilder* segment)) { // Check that the target is really in the same segment, otherwise subtracting pointers is // undefined behavior. As it turns out, it's undefined behavior that actually produces // unexpected results in a real-world situation that actually happened: At one time, // OrphanBuilder's "tag" (a WirePointer) was allowed to be initialized as if it lived in // a particular segment when in fact it does not. On 32-bit systems, where words might // only be 32-bit aligned, it's possible that the difference between `this` and `target` is // not a whole number of words. But clang optimizes: // (target - (word*)this - 1) << 2 // to: // (((ptrdiff_t)target - (ptrdiff_t)this - 8) >> 1) // So now when the pointers are not aligned the same, we can end up corrupting the bottom // two bits, where `kind` is stored. For example, this turns a struct into a far pointer. // Ouch! KJ_DREQUIRE(reinterpret_cast(this) >= reinterpret_cast(segment->getStartPtr())); KJ_DREQUIRE(reinterpret_cast(this) < reinterpret_cast(segment->getStartPtr() + segment->getSize())); KJ_DREQUIRE(reinterpret_cast(target) >= reinterpret_cast(segment->getStartPtr())); KJ_DREQUIRE(reinterpret_cast(target) <= reinterpret_cast(segment->getStartPtr() + segment->getSize())); offsetAndKind.set((static_cast(target - reinterpret_cast(this) - 1) << 2) | kind); } KJ_ALWAYS_INLINE(void setKindWithZeroOffset(Kind kind)) { offsetAndKind.set(kind); } KJ_ALWAYS_INLINE(void setKindAndTargetForEmptyStruct()) { // This pointer points at an empty struct. Assuming the WirePointer itself is in-bounds, we // can set the target to point either at the WirePointer itself or immediately after it. The // latter would cause the WirePointer to be "null" (since for an empty struct the upper 32 // bits are going to be zero). So we set an offset of -1, as if the struct were allocated // immediately before this pointer, to distinguish it from null. offsetAndKind.set(0xfffffffc); } KJ_ALWAYS_INLINE(void setKindForOrphan(Kind kind)) { // OrphanBuilder contains a WirePointer, but since it isn't located in a segment, it should // not have a valid offset (unless it is a FAR or OTHER pointer). We set its offset to -1 // because setting it to zero would mean a pointer to an empty struct would appear to be a null // pointer. KJ_DREQUIRE(isPositional()); offsetAndKind.set(kind | 0xfffffffc); } KJ_ALWAYS_INLINE(ListElementCount inlineCompositeListElementCount() const) { return ((bounded(offsetAndKind.get()) >> G(2)) & G(kj::maxValueForBits())) * ELEMENTS; } KJ_ALWAYS_INLINE(void setKindAndInlineCompositeListElementCount( Kind kind, ListElementCount elementCount)) { offsetAndKind.set(unboundAs((elementCount / ELEMENTS) << G(2)) | kind); } KJ_ALWAYS_INLINE(const word* farTarget(SegmentReader* segment) const) { KJ_DREQUIRE(kind() == FAR, "farTarget() should only be called on FAR pointers."); return segment->checkOffset(segment->getStartPtr(), offsetAndKind.get() >> 3); } KJ_ALWAYS_INLINE(word* farTarget(SegmentBuilder* segment) const) { KJ_DREQUIRE(kind() == FAR, "farTarget() should only be called on FAR pointers."); return segment->getPtrUnchecked((bounded(offsetAndKind.get()) >> G(3)) * WORDS); } KJ_ALWAYS_INLINE(bool isDoubleFar() const) { KJ_DREQUIRE(kind() == FAR, "isDoubleFar() should only be called on FAR pointers."); return (offsetAndKind.get() >> 2) & 1; } KJ_ALWAYS_INLINE(void setFar(bool isDoubleFar, WordCountN<29> pos)) { offsetAndKind.set(unboundAs((pos / WORDS) << G(3)) | (static_cast(isDoubleFar) << 2) | static_cast(Kind::FAR)); } KJ_ALWAYS_INLINE(void setCap(uint index)) { offsetAndKind.set(static_cast(Kind::OTHER)); capRef.index.set(index); } // ----------------------------------------------------------------- // Part of pointer that depends on the kind. // Note: Originally StructRef, ListRef, and FarRef were unnamed types, but this somehow // tickled a bug in GCC: // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58192 struct StructRef { WireValue dataSize; WireValue ptrCount; inline WordCountN<17> wordSize() const { return upgradeBound(dataSize.get()) + ptrCount.get() * WORDS_PER_POINTER; } KJ_ALWAYS_INLINE(void set(WordCount16 ds, WirePointerCount16 rc)) { dataSize.set(ds); ptrCount.set(rc); } KJ_ALWAYS_INLINE(void set(StructSize size)) { dataSize.set(size.data); ptrCount.set(size.pointers); } }; struct ListRef { WireValue elementSizeAndCount; KJ_ALWAYS_INLINE(ElementSize elementSize() const) { return static_cast(elementSizeAndCount.get() & 7); } KJ_ALWAYS_INLINE(ElementCountN<29> elementCount() const) { return (bounded(elementSizeAndCount.get()) >> G(3)) * ELEMENTS; } KJ_ALWAYS_INLINE(WordCountN<29> inlineCompositeWordCount() const) { return elementCount() * (ONE * WORDS / ELEMENTS); } KJ_ALWAYS_INLINE(void set(ElementSize es, ElementCountN<29> ec)) { elementSizeAndCount.set(unboundAs((ec / ELEMENTS) << G(3)) | static_cast(es)); } KJ_ALWAYS_INLINE(void setInlineComposite(WordCountN<29> wc)) { elementSizeAndCount.set(unboundAs((wc / WORDS) << G(3)) | static_cast(ElementSize::INLINE_COMPOSITE)); } }; struct FarRef { WireValue segmentId; KJ_ALWAYS_INLINE(void set(SegmentId si)) { segmentId.set(si); } }; struct CapRef { WireValue index; // Index into the message's capability table. }; union { uint32_t upper32Bits; StructRef structRef; ListRef listRef; FarRef farRef; CapRef capRef; }; KJ_ALWAYS_INLINE(bool isNull() const) { // If the upper 32 bits are zero, this is a pointer to an empty struct. We consider that to be // our "null" value. return (offsetAndKind.get() == 0) & (upper32Bits == 0); } }; static_assert(sizeof(WirePointer) == sizeof(word), "capnp::WirePointer is not exactly one word. This will probably break everything."); static_assert(unboundAs(POINTERS * WORDS_PER_POINTER * BYTES_PER_WORD / BYTES) == sizeof(WirePointer), "WORDS_PER_POINTER is wrong."); static_assert(unboundAs(POINTERS * BYTES_PER_POINTER / BYTES) == sizeof(WirePointer), "BYTES_PER_POINTER is wrong."); static_assert(unboundAs(POINTERS * BITS_PER_POINTER / BITS_PER_BYTE / BYTES) == sizeof(WirePointer), "BITS_PER_POINTER is wrong."); #define OUT_OF_BOUNDS_ERROR_DETAIL \ "This usually indicates that " \ "the input data was corrupted, used a different encoding than specified (e.g. " \ "packed vs. non-packed), or was not a Cap'n Proto message to begin with. Note " \ "that this error is NOT due to a schema mismatch; the input is invalid " \ "regardless of schema." namespace { static const union { AlignedData word; WirePointer pointer; } zero = {{{0}}}; } // namespace // ======================================================================================= namespace { template struct SegmentAnd { SegmentBuilder* segment; T value; }; } // namespace struct WireHelpers { #if CAPNP_DEBUG_TYPES template static KJ_ALWAYS_INLINE( kj::Quantity, word> roundBytesUpToWords( kj::Quantity, byte> bytes)) { static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); return (bytes + G(7) * BYTES) / BYTES_PER_WORD; } template static KJ_ALWAYS_INLINE( kj::Quantity, byte> roundBitsUpToBytes( kj::Quantity, BitLabel> bits)) { return (bits + G(7) * BITS) / BITS_PER_BYTE; } template static KJ_ALWAYS_INLINE( kj::Quantity, word> roundBitsUpToWords( kj::Quantity, BitLabel> bits)) { static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); return (bits + G(63) * BITS) / BITS_PER_WORD; } #else static KJ_ALWAYS_INLINE(WordCount roundBytesUpToWords(ByteCount bytes)) { static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); return (bytes + G(7) * BYTES) / BYTES_PER_WORD; } static KJ_ALWAYS_INLINE(ByteCount roundBitsUpToBytes(BitCount bits)) { return (bits + G(7) * BITS) / BITS_PER_BYTE; } static KJ_ALWAYS_INLINE(WordCount64 roundBitsUpToWords(BitCount64 bits)) { static_assert(sizeof(word) == 8, "This code assumes 64-bit words."); return (bits + G(63) * BITS) / BITS_PER_WORD; } static KJ_ALWAYS_INLINE(ByteCount64 roundBitsUpToBytes(BitCount64 bits)) { return (bits + G(7) * BITS) / BITS_PER_BYTE; } #endif static KJ_ALWAYS_INLINE(void zeroMemory(byte* ptr, ByteCount32 count)) { if (count != ZERO * BYTES) memset(ptr, 0, unbound(count / BYTES)); } static KJ_ALWAYS_INLINE(void zeroMemory(word* ptr, WordCountN<29> count)) { if (count != ZERO * WORDS) memset(ptr, 0, unbound(count * BYTES_PER_WORD / BYTES)); } static KJ_ALWAYS_INLINE(void zeroMemory(WirePointer* ptr, WirePointerCountN<29> count)) { if (count != ZERO * POINTERS) memset(ptr, 0, unbound(count * BYTES_PER_POINTER / BYTES)); } static KJ_ALWAYS_INLINE(void zeroMemory(WirePointer* ptr)) { memset(ptr, 0, sizeof(*ptr)); } template static inline void zeroMemory(kj::ArrayPtr array) { if (array.size() != 0u) memset(array.begin(), 0, array.size() * sizeof(array[0])); } static KJ_ALWAYS_INLINE(void copyMemory(byte* to, const byte* from, ByteCount32 count)) { if (count != ZERO * BYTES) memcpy(to, from, unbound(count / BYTES)); } static KJ_ALWAYS_INLINE(void copyMemory(word* to, const word* from, WordCountN<29> count)) { if (count != ZERO * WORDS) memcpy(to, from, unbound(count * BYTES_PER_WORD / BYTES)); } static KJ_ALWAYS_INLINE(void copyMemory(WirePointer* to, const WirePointer* from, WirePointerCountN<29> count)) { if (count != ZERO * POINTERS) memcpy(to, from, unbound(count * BYTES_PER_POINTER / BYTES)); } template static inline void copyMemory(T* to, const T* from) { memcpy(to, from, sizeof(*from)); } // TODO(cleanup): Turn these into a .copyTo() method of ArrayPtr? template static inline void copyMemory(T* to, kj::ArrayPtr from) { if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); } template static inline void copyMemory(T* to, kj::ArrayPtr from) { if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); } static KJ_ALWAYS_INLINE(void copyMemory(char* to, kj::StringPtr from)) { if (from.size() != 0u) memcpy(to, from.begin(), from.size() * sizeof(from[0])); } static KJ_ALWAYS_INLINE(bool boundsCheck( SegmentReader* segment, const word* start, WordCountN<31> size)) { // If segment is null, this is an unchecked message, so we don't do bounds checks. return segment == nullptr || segment->checkObject(start, size); } static KJ_ALWAYS_INLINE(bool amplifiedRead(SegmentReader* segment, WordCount virtualAmount)) { // If segment is null, this is an unchecked message, so we don't do read limiter checks. return segment == nullptr || segment->amplifiedRead(virtualAmount); } static KJ_ALWAYS_INLINE(word* allocate( WirePointer*& ref, SegmentBuilder*& segment, CapTableBuilder* capTable, SegmentWordCount amount, WirePointer::Kind kind, BuilderArena* orphanArena)) { // Allocate space in the message for a new object, creating far pointers if necessary. The // space is guaranteed to be zero'd (because MessageBuilder implementations are required to // return zero'd memory). // // * `ref` starts out being a reference to the pointer which shall be assigned to point at the // new object. On return, `ref` points to a pointer which needs to be initialized with // the object's type information. Normally this is the same pointer, but it can change if // a far pointer was allocated -- in this case, `ref` will end up pointing to the far // pointer's tag. Either way, `allocate()` takes care of making sure that the original // pointer ends up leading to the new object. On return, only the upper 32 bit of `*ref` // need to be filled in by the caller. // * `segment` starts out pointing to the segment containing `ref`. On return, it points to // the segment containing the allocated object, which is usually the same segment but could // be a different one if the original segment was out of space. // * `amount` is the number of words to allocate. // * `kind` is the kind of object to allocate. It is used to initialize the pointer. It // cannot be `FAR` -- far pointers are allocated automatically as needed. // * `orphanArena` is usually null. If it is non-null, then we're allocating an orphan object. // In this case, `segment` starts out null; the allocation takes place in an arbitrary // segment belonging to the arena. `ref` will be initialized as a non-far pointer, but its // target offset will be set to zero. if (orphanArena == nullptr) { if (!ref->isNull()) zeroObject(segment, capTable, ref); if (amount == ZERO * WORDS && kind == WirePointer::STRUCT) { // Note that the check for kind == WirePointer::STRUCT will hopefully cause this whole // branch to be optimized away from all the call sites that are allocating non-structs. ref->setKindAndTargetForEmptyStruct(); return reinterpret_cast(ref); } KJ_ASSUME(segment != nullptr); word* ptr = segment->allocate(amount); if (ptr == nullptr) { // Need to allocate in a new segment. We'll need to allocate an extra pointer worth of // space to act as the landing pad for a far pointer. WordCount amountPlusRef = amount + POINTER_SIZE_IN_WORDS; auto allocation = segment->getArena()->allocate( assertMaxBits(amountPlusRef, []() { KJ_FAIL_REQUIRE("requested object size exceeds maximum segment size"); })); segment = allocation.segment; ptr = allocation.words; // Set up the original pointer to be a far pointer to the new segment. ref->setFar(false, segment->getOffsetTo(ptr)); ref->farRef.set(segment->getSegmentId()); // Initialize the landing pad to indicate that the data immediately follows the pad. ref = reinterpret_cast(ptr); ref->setKindAndTarget(kind, ptr + POINTER_SIZE_IN_WORDS, segment); // Allocated space follows new pointer. return ptr + POINTER_SIZE_IN_WORDS; } else { ref->setKindAndTarget(kind, ptr, segment); return ptr; } } else { // orphanArena is non-null. Allocate an orphan. KJ_DASSERT(ref->isNull()); auto allocation = orphanArena->allocate(amount); segment = allocation.segment; ref->setKindForOrphan(kind); return allocation.words; } } static KJ_ALWAYS_INLINE(word* followFarsNoWritableCheck( WirePointer*& ref, word* refTarget, SegmentBuilder*& segment)) { // If `ref` is a far pointer, follow it. On return, `ref` will have been updated to point at // a WirePointer that contains the type information about the target object, and a pointer to // the object contents is returned. The caller must NOT use `ref->target()` as this may or may // not actually return a valid pointer. `segment` is also updated to point at the segment which // actually contains the object. // // If `ref` is not a far pointer, this simply returns `refTarget`. Usually, `refTarget` should // be the same as `ref->target()`, but may not be in cases where `ref` is only a tag. if (ref->kind() == WirePointer::FAR) { segment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); WirePointer* pad = reinterpret_cast(ref->farTarget(segment)); if (!ref->isDoubleFar()) { ref = pad; return pad->target(); } // Landing pad is another far pointer. It is followed by a tag describing the pointed-to // object. ref = pad + 1; segment = segment->getArena()->getSegment(pad->farRef.segmentId.get()); return pad->farTarget(segment); } else { return refTarget; } } static KJ_ALWAYS_INLINE(word* followFars( WirePointer*& ref, word* refTarget, SegmentBuilder*& segment)) { auto result = followFarsNoWritableCheck(ref, refTarget, segment); segment->checkWritable(); return result; } static KJ_ALWAYS_INLINE(kj::Maybe followFars( const WirePointer*& ref, const word* refTarget, SegmentReader*& segment)) KJ_WARN_UNUSED_RESULT { // Like the other followFars() but operates on readers. // If the segment is null, this is an unchecked message, so there are no FAR pointers. if (segment != nullptr && ref->kind() == WirePointer::FAR) { // Look up the segment containing the landing pad. segment = segment->getArena()->tryGetSegment(ref->farRef.segmentId.get()); KJ_REQUIRE(segment != nullptr, "Message contains far pointer to unknown segment.") { return nullptr; } // Find the landing pad and check that it is within bounds. const word* ptr = ref->farTarget(segment); auto padWords = (ONE + bounded(ref->isDoubleFar())) * POINTER_SIZE_IN_WORDS; KJ_REQUIRE(boundsCheck(segment, ptr, padWords), "Message contains out-of-bounds far pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { return nullptr; } const WirePointer* pad = reinterpret_cast(ptr); // If this is not a double-far then the landing pad is our final pointer. if (!ref->isDoubleFar()) { ref = pad; return pad->target(segment); } // Landing pad is another far pointer. It is followed by a tag describing the pointed-to // object. ref = pad + 1; SegmentReader* newSegment = segment->getArena()->tryGetSegment(pad->farRef.segmentId.get()); KJ_REQUIRE(newSegment != nullptr, "Message contains double-far pointer to unknown segment.") { return nullptr; } KJ_REQUIRE(pad->kind() == WirePointer::FAR, "Second word of double-far pad must be far pointer.") { return nullptr; } segment = newSegment; return pad->farTarget(segment); } else { KJ_DASSERT(refTarget != nullptr); return refTarget; } } // ----------------------------------------------------------------- static void zeroObject(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref) { // Zero out the pointed-to object. Use when the pointer is about to be overwritten making the // target object no longer reachable. // We shouldn't zero out external data linked into the message. if (!segment->isWritable()) return; switch (ref->kind()) { case WirePointer::STRUCT: case WirePointer::LIST: zeroObject(segment, capTable, ref, ref->target()); break; case WirePointer::FAR: { segment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); if (segment->isWritable()) { // Don't zero external data. WirePointer* pad = reinterpret_cast(ref->farTarget(segment)); if (ref->isDoubleFar()) { segment = segment->getArena()->getSegment(pad->farRef.segmentId.get()); if (segment->isWritable()) { zeroObject(segment, capTable, pad + 1, pad->farTarget(segment)); } zeroMemory(pad, G(2) * POINTERS); } else { zeroObject(segment, capTable, pad); zeroMemory(pad); } } break; } case WirePointer::OTHER: if (ref->isCapability()) { #if CAPNP_LITE KJ_FAIL_ASSERT("Capability encountered in builder in lite mode?") { break; } #else // CAPNP_LINE capTable->dropCap(ref->capRef.index.get()); #endif // CAPNP_LITE, else } else { KJ_FAIL_REQUIRE("Unknown pointer type.") { break; } } break; } } static void zeroObject(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* tag, word* ptr) { // We shouldn't zero out external data linked into the message. if (!segment->isWritable()) return; switch (tag->kind()) { case WirePointer::STRUCT: { WirePointer* pointerSection = reinterpret_cast(ptr + tag->structRef.dataSize.get()); for (auto i: kj::zeroTo(tag->structRef.ptrCount.get())) { zeroObject(segment, capTable, pointerSection + i); } zeroMemory(ptr, tag->structRef.wordSize()); break; } case WirePointer::LIST: { switch (tag->listRef.elementSize()) { case ElementSize::VOID: // Nothing. break; case ElementSize::BIT: case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: { zeroMemory(ptr, roundBitsUpToWords( upgradeBound(tag->listRef.elementCount()) * dataBitsPerElement(tag->listRef.elementSize()))); break; } case ElementSize::POINTER: { WirePointer* typedPtr = reinterpret_cast(ptr); auto count = tag->listRef.elementCount() * (ONE * POINTERS / ELEMENTS); for (auto i: kj::zeroTo(count)) { zeroObject(segment, capTable, typedPtr + i); } zeroMemory(typedPtr, count); break; } case ElementSize::INLINE_COMPOSITE: { WirePointer* elementTag = reinterpret_cast(ptr); KJ_ASSERT(elementTag->kind() == WirePointer::STRUCT, "Don't know how to handle non-STRUCT inline composite."); WordCount dataSize = elementTag->structRef.dataSize.get(); WirePointerCount pointerCount = elementTag->structRef.ptrCount.get(); auto count = elementTag->inlineCompositeListElementCount(); if (pointerCount > ZERO * POINTERS) { word* pos = ptr + POINTER_SIZE_IN_WORDS; for (auto i KJ_UNUSED: kj::zeroTo(count)) { pos += dataSize; for (auto j KJ_UNUSED: kj::zeroTo(pointerCount)) { zeroObject(segment, capTable, reinterpret_cast(pos)); pos += POINTER_SIZE_IN_WORDS; } } } auto wordsPerElement = elementTag->structRef.wordSize() / ELEMENTS; zeroMemory(ptr, assertMaxBits(POINTER_SIZE_IN_WORDS + upgradeBound(count) * wordsPerElement, []() { KJ_FAIL_ASSERT("encountered list pointer in builder which is too large to " "possibly fit in a segment. Bug in builder code?"); })); break; } } break; } case WirePointer::FAR: KJ_FAIL_ASSERT("Unexpected FAR pointer.") { break; } break; case WirePointer::OTHER: KJ_FAIL_ASSERT("Unexpected OTHER pointer.") { break; } break; } } static KJ_ALWAYS_INLINE( void zeroPointerAndFars(SegmentBuilder* segment, WirePointer* ref)) { // Zero out the pointer itself and, if it is a far pointer, zero the landing pad as well, but // do not zero the object body. Used when upgrading. if (ref->kind() == WirePointer::FAR) { SegmentBuilder* padSegment = segment->getArena()->getSegment(ref->farRef.segmentId.get()); if (padSegment->isWritable()) { // Don't zero external data. WirePointer* pad = reinterpret_cast(ref->farTarget(padSegment)); if (ref->isDoubleFar()) { zeroMemory(pad, G(2) * POINTERS); } else { zeroMemory(pad); } } } zeroMemory(ref); } // ----------------------------------------------------------------- static MessageSizeCounts totalSize( SegmentReader* segment, const WirePointer* ref, int nestingLimit) { // Compute the total size of the object pointed to, not counting far pointer overhead. MessageSizeCounts result = { ZERO * WORDS, 0 }; if (ref->isNull()) { return result; } KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested.") { return result; } --nestingLimit; const word* ptr; KJ_IF_MAYBE(p, followFars(ref, ref->target(segment), segment)) { ptr = p; } else { return result; } switch (ref->kind()) { case WirePointer::STRUCT: { KJ_REQUIRE(boundsCheck(segment, ptr, ref->structRef.wordSize()), "Message contained out-of-bounds struct pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { return result; } result.addWords(ref->structRef.wordSize()); const WirePointer* pointerSection = reinterpret_cast(ptr + ref->structRef.dataSize.get()); for (auto i: kj::zeroTo(ref->structRef.ptrCount.get())) { result += totalSize(segment, pointerSection + i, nestingLimit); } break; } case WirePointer::LIST: { switch (ref->listRef.elementSize()) { case ElementSize::VOID: // Nothing. break; case ElementSize::BIT: case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: { auto totalWords = roundBitsUpToWords( upgradeBound(ref->listRef.elementCount()) * dataBitsPerElement(ref->listRef.elementSize())); KJ_REQUIRE(boundsCheck(segment, ptr, totalWords), "Message contained out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { return result; } result.addWords(totalWords); break; } case ElementSize::POINTER: { auto count = ref->listRef.elementCount() * (POINTERS / ELEMENTS); KJ_REQUIRE(boundsCheck(segment, ptr, count * WORDS_PER_POINTER), "Message contained out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { return result; } result.addWords(count * WORDS_PER_POINTER); for (auto i: kj::zeroTo(count)) { result += totalSize(segment, reinterpret_cast(ptr) + i, nestingLimit); } break; } case ElementSize::INLINE_COMPOSITE: { auto wordCount = ref->listRef.inlineCompositeWordCount(); KJ_REQUIRE(boundsCheck(segment, ptr, wordCount + POINTER_SIZE_IN_WORDS), "Message contained out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { return result; } const WirePointer* elementTag = reinterpret_cast(ptr); auto count = elementTag->inlineCompositeListElementCount(); KJ_REQUIRE(elementTag->kind() == WirePointer::STRUCT, "Don't know how to handle non-STRUCT inline composite.") { return result; } auto actualSize = elementTag->structRef.wordSize() / ELEMENTS * upgradeBound(count); KJ_REQUIRE(actualSize <= wordCount, "Struct list pointer's elements overran size. " OUT_OF_BOUNDS_ERROR_DETAIL) { return result; } // We count the actual size rather than the claimed word count because that's what // we'll end up with if we make a copy. result.addWords(actualSize + POINTER_SIZE_IN_WORDS); WordCount dataSize = elementTag->structRef.dataSize.get(); WirePointerCount pointerCount = elementTag->structRef.ptrCount.get(); if (pointerCount > ZERO * POINTERS) { const word* pos = ptr + POINTER_SIZE_IN_WORDS; for (auto i KJ_UNUSED: kj::zeroTo(count)) { pos += dataSize; for (auto j KJ_UNUSED: kj::zeroTo(pointerCount)) { result += totalSize(segment, reinterpret_cast(pos), nestingLimit); pos += POINTER_SIZE_IN_WORDS; } } } break; } } break; } case WirePointer::FAR: KJ_FAIL_REQUIRE("Unexpected FAR pointer.") { break; } break; case WirePointer::OTHER: if (ref->isCapability()) { result.capCount++; } else { KJ_FAIL_REQUIRE("Unknown pointer type.") { break; } } break; } return result; } // ----------------------------------------------------------------- // Copy from an unchecked message. static KJ_ALWAYS_INLINE( void copyStruct(SegmentBuilder* segment, CapTableBuilder* capTable, word* dst, const word* src, StructDataWordCount dataSize, StructPointerCount pointerCount)) { copyMemory(dst, src, dataSize); const WirePointer* srcRefs = reinterpret_cast(src + dataSize); WirePointer* dstRefs = reinterpret_cast(dst + dataSize); for (auto i: kj::zeroTo(pointerCount)) { SegmentBuilder* subSegment = segment; WirePointer* dstRef = dstRefs + i; copyMessage(subSegment, capTable, dstRef, srcRefs + i); } } static word* copyMessage( SegmentBuilder*& segment, CapTableBuilder* capTable, WirePointer*& dst, const WirePointer* src) { // Not always-inline because it's recursive. switch (src->kind()) { case WirePointer::STRUCT: { if (src->isNull()) { zeroMemory(dst); return nullptr; } else { const word* srcPtr = src->target(nullptr); word* dstPtr = allocate( dst, segment, capTable, src->structRef.wordSize(), WirePointer::STRUCT, nullptr); copyStruct(segment, capTable, dstPtr, srcPtr, src->structRef.dataSize.get(), src->structRef.ptrCount.get()); dst->structRef.set(src->structRef.dataSize.get(), src->structRef.ptrCount.get()); return dstPtr; } } case WirePointer::LIST: { switch (src->listRef.elementSize()) { case ElementSize::VOID: case ElementSize::BIT: case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: { auto wordCount = roundBitsUpToWords( upgradeBound(src->listRef.elementCount()) * dataBitsPerElement(src->listRef.elementSize())); const word* srcPtr = src->target(nullptr); word* dstPtr = allocate(dst, segment, capTable, wordCount, WirePointer::LIST, nullptr); copyMemory(dstPtr, srcPtr, wordCount); dst->listRef.set(src->listRef.elementSize(), src->listRef.elementCount()); return dstPtr; } case ElementSize::POINTER: { const WirePointer* srcRefs = reinterpret_cast(src->target(nullptr)); WirePointer* dstRefs = reinterpret_cast( allocate(dst, segment, capTable, src->listRef.elementCount() * (ONE * POINTERS / ELEMENTS) * WORDS_PER_POINTER, WirePointer::LIST, nullptr)); for (auto i: kj::zeroTo(src->listRef.elementCount() * (ONE * POINTERS / ELEMENTS))) { SegmentBuilder* subSegment = segment; WirePointer* dstRef = dstRefs + i; copyMessage(subSegment, capTable, dstRef, srcRefs + i); } dst->listRef.set(ElementSize::POINTER, src->listRef.elementCount()); return reinterpret_cast(dstRefs); } case ElementSize::INLINE_COMPOSITE: { const word* srcPtr = src->target(nullptr); word* dstPtr = allocate(dst, segment, capTable, assertMaxBits( src->listRef.inlineCompositeWordCount() + POINTER_SIZE_IN_WORDS, []() { KJ_FAIL_ASSERT("list too big to fit in a segment"); }), WirePointer::LIST, nullptr); dst->listRef.setInlineComposite(src->listRef.inlineCompositeWordCount()); const WirePointer* srcTag = reinterpret_cast(srcPtr); copyMemory(reinterpret_cast(dstPtr), srcTag); const word* srcElement = srcPtr + POINTER_SIZE_IN_WORDS; word* dstElement = dstPtr + POINTER_SIZE_IN_WORDS; KJ_ASSERT(srcTag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE of lists is not yet supported."); for (auto i KJ_UNUSED: kj::zeroTo(srcTag->inlineCompositeListElementCount())) { copyStruct(segment, capTable, dstElement, srcElement, srcTag->structRef.dataSize.get(), srcTag->structRef.ptrCount.get()); srcElement += srcTag->structRef.wordSize(); dstElement += srcTag->structRef.wordSize(); } return dstPtr; } } break; } case WirePointer::OTHER: KJ_FAIL_REQUIRE("Unchecked messages cannot contain OTHER pointers (e.g. capabilities)."); break; case WirePointer::FAR: KJ_FAIL_REQUIRE("Unchecked messages cannot contain far pointers."); break; } return nullptr; } static void transferPointer(SegmentBuilder* dstSegment, WirePointer* dst, SegmentBuilder* srcSegment, WirePointer* src) { // Make *dst point to the same object as *src. Both must reside in the same message, but can // be in different segments. Not always-inline because this is rarely used. // // Caller MUST zero out the source pointer after calling this, to make sure no later code // mistakenly thinks the source location still owns the object. transferPointer() doesn't do // this zeroing itself because many callers transfer several pointers in a loop then zero out // the whole section. KJ_DASSERT(dst->isNull()); // We expect the caller to ensure the target is already null so won't leak. if (src->isNull()) { zeroMemory(dst); } else if (src->isPositional()) { transferPointer(dstSegment, dst, srcSegment, src, src->target()); } else { // Far and other pointers are position-independent, so we can just copy. copyMemory(dst, src); } } static void transferPointer(SegmentBuilder* dstSegment, WirePointer* dst, SegmentBuilder* srcSegment, const WirePointer* srcTag, word* srcPtr) { // Like the other overload, but splits src into a tag and a target. Particularly useful for // OrphanBuilder. if (dstSegment == srcSegment) { // Same segment, so create a direct pointer. if (srcTag->kind() == WirePointer::STRUCT && srcTag->structRef.wordSize() == ZERO * WORDS) { dst->setKindAndTargetForEmptyStruct(); } else { dst->setKindAndTarget(srcTag->kind(), srcPtr, dstSegment); } // We can just copy the upper 32 bits. (Use memcpy() to comply with aliasing rules.) copyMemory(&dst->upper32Bits, &srcTag->upper32Bits); } else { // Need to create a far pointer. Try to allocate it in the same segment as the source, so // that it doesn't need to be a double-far. WirePointer* landingPad = reinterpret_cast(srcSegment->allocate(G(1) * WORDS)); if (landingPad == nullptr) { // Darn, need a double-far. auto allocation = srcSegment->getArena()->allocate(G(2) * WORDS); SegmentBuilder* farSegment = allocation.segment; landingPad = reinterpret_cast(allocation.words); landingPad[0].setFar(false, srcSegment->getOffsetTo(srcPtr)); landingPad[0].farRef.segmentId.set(srcSegment->getSegmentId()); landingPad[1].setKindWithZeroOffset(srcTag->kind()); copyMemory(&landingPad[1].upper32Bits, &srcTag->upper32Bits); dst->setFar(true, farSegment->getOffsetTo(reinterpret_cast(landingPad))); dst->farRef.set(farSegment->getSegmentId()); } else { // Simple landing pad is just a pointer. landingPad->setKindAndTarget(srcTag->kind(), srcPtr, srcSegment); copyMemory(&landingPad->upper32Bits, &srcTag->upper32Bits); dst->setFar(false, srcSegment->getOffsetTo(reinterpret_cast(landingPad))); dst->farRef.set(srcSegment->getSegmentId()); } } } // ----------------------------------------------------------------- static KJ_ALWAYS_INLINE(StructBuilder initStructPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, StructSize size, BuilderArena* orphanArena = nullptr)) { // Allocate space for the new struct. Newly-allocated space is automatically zeroed. word* ptr = allocate(ref, segment, capTable, size.total(), WirePointer::STRUCT, orphanArena); // Initialize the pointer. ref->structRef.set(size); // Build the StructBuilder. return StructBuilder(segment, capTable, ptr, reinterpret_cast(ptr + size.data), size.data * BITS_PER_WORD, size.pointers); } static KJ_ALWAYS_INLINE(StructBuilder getWritableStructPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, StructSize size, const word* defaultValue)) { return getWritableStructPointer(ref, ref->target(), segment, capTable, size, defaultValue); } static KJ_ALWAYS_INLINE(StructBuilder getWritableStructPointer( WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable, StructSize size, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { if (ref->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return initStructPointer(ref, segment, capTable, size, orphanArena); } refTarget = copyMessage(segment, capTable, ref, reinterpret_cast(defaultValue)); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } WirePointer* oldRef = ref; SegmentBuilder* oldSegment = segment; word* oldPtr = followFars(oldRef, refTarget, oldSegment); KJ_REQUIRE(oldRef->kind() == WirePointer::STRUCT, "Schema mismatch: Message contains non-struct pointer where struct pointer was expected.") { goto useDefault; } auto oldDataSize = oldRef->structRef.dataSize.get(); auto oldPointerCount = oldRef->structRef.ptrCount.get(); WirePointer* oldPointerSection = reinterpret_cast(oldPtr + oldDataSize); if (oldDataSize < size.data || oldPointerCount < size.pointers) { // The space allocated for this struct is too small. Unlike with readers, we can't just // run with it and do bounds checks at access time, because how would we handle writes? // Instead, we have to copy the struct to a new space now. auto newDataSize = kj::max(oldDataSize, size.data); auto newPointerCount = kj::max(oldPointerCount, size.pointers); auto totalSize = newDataSize + newPointerCount * WORDS_PER_POINTER; // Don't let allocate() zero out the object just yet. zeroPointerAndFars(segment, ref); word* ptr = allocate(ref, segment, capTable, totalSize, WirePointer::STRUCT, orphanArena); ref->structRef.set(newDataSize, newPointerCount); // Copy data section. copyMemory(ptr, oldPtr, oldDataSize); // Copy pointer section. WirePointer* newPointerSection = reinterpret_cast(ptr + newDataSize); for (auto i: kj::zeroTo(oldPointerCount)) { transferPointer(segment, newPointerSection + i, oldSegment, oldPointerSection + i); } // Zero out old location. This has two purposes: // 1) We don't want to leak the original contents of the struct when the message is written // out as it may contain secrets that the caller intends to remove from the new copy. // 2) Zeros will be deflated by packing, making this dead memory almost-free if it ever // hits the wire. zeroMemory(oldPtr, oldDataSize + oldPointerCount * WORDS_PER_POINTER); return StructBuilder(segment, capTable, ptr, newPointerSection, newDataSize * BITS_PER_WORD, newPointerCount); } else { return StructBuilder(oldSegment, capTable, oldPtr, oldPointerSection, oldDataSize * BITS_PER_WORD, oldPointerCount); } } static KJ_ALWAYS_INLINE(ListBuilder initListPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, ElementCount elementCount, ElementSize elementSize, BuilderArena* orphanArena = nullptr)) { KJ_DREQUIRE(elementSize != ElementSize::INLINE_COMPOSITE, "Should have called initStructListPointer() instead."); auto checkedElementCount = assertMaxBits(elementCount, []() { KJ_FAIL_REQUIRE("tried to allocate list with too many elements"); }); auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; auto step = bitsPerElementIncludingPointers(elementSize); KJ_DASSERT(step * ELEMENTS == (dataSize + pointerCount * BITS_PER_POINTER)); // Calculate size of the list. auto wordCount = roundBitsUpToWords(upgradeBound(checkedElementCount) * step); // Allocate the list. word* ptr = allocate(ref, segment, capTable, wordCount, WirePointer::LIST, orphanArena); // Initialize the pointer. ref->listRef.set(elementSize, checkedElementCount); // Build the ListBuilder. return ListBuilder(segment, capTable, ptr, step, checkedElementCount, dataSize, pointerCount, elementSize); } static KJ_ALWAYS_INLINE(ListBuilder initStructListPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, ElementCount elementCount, StructSize elementSize, BuilderArena* orphanArena = nullptr)) { auto checkedElementCount = assertMaxBits(elementCount, []() { KJ_FAIL_REQUIRE("tried to allocate list with too many elements"); }); WordsPerElementN<17> wordsPerElement = elementSize.total() / ELEMENTS; // Allocate the list, prefixed by a single WirePointer. auto wordCount = assertMax() - 1>( upgradeBound(checkedElementCount) * wordsPerElement, []() { KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size"); }); word* ptr = allocate(ref, segment, capTable, POINTER_SIZE_IN_WORDS + wordCount, WirePointer::LIST, orphanArena); // Initialize the pointer. // INLINE_COMPOSITE lists replace the element count with the word count. ref->listRef.setInlineComposite(wordCount); // Initialize the list tag. reinterpret_cast(ptr)->setKindAndInlineCompositeListElementCount( WirePointer::STRUCT, checkedElementCount); reinterpret_cast(ptr)->structRef.set(elementSize); ptr += POINTER_SIZE_IN_WORDS; // Build the ListBuilder. return ListBuilder(segment, capTable, ptr, wordsPerElement * BITS_PER_WORD, checkedElementCount, elementSize.data * BITS_PER_WORD, elementSize.pointers, ElementSize::INLINE_COMPOSITE); } static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointer( WirePointer* origRef, SegmentBuilder* origSegment, CapTableBuilder* capTable, ElementSize elementSize, const word* defaultValue)) { return getWritableListPointer(origRef, origRef->target(), origSegment, capTable, elementSize, defaultValue); } static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointer( WirePointer* origRef, word* origRefTarget, SegmentBuilder* origSegment, CapTableBuilder* capTable, ElementSize elementSize, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { KJ_DREQUIRE(elementSize != ElementSize::INLINE_COMPOSITE, "Use getWritableStructListPointer() for struct lists."); if (origRef->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return ListBuilder(elementSize); } origRefTarget = copyMessage( origSegment, capTable, origRef, reinterpret_cast(defaultValue)); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } // We must verify that the pointer has the right size. Unlike in // getWritableStructListPointer(), we never need to "upgrade" the data, because this // method is called only for non-struct lists, and there is no allowed upgrade path *to* // a non-struct list, only *from* them. WirePointer* ref = origRef; SegmentBuilder* segment = origSegment; word* ptr = followFars(ref, origRefTarget, segment); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Called getWritableListPointer() but existing pointer is not a list.") { goto useDefault; } ElementSize oldSize = ref->listRef.elementSize(); if (oldSize == ElementSize::INLINE_COMPOSITE) { // The existing element size is INLINE_COMPOSITE, though we expected a list of primitives. // The existing data must have been written with a newer version of the protocol. We // therefore never need to upgrade the data in this case, but we do need to validate that it // is a valid upgrade from what we expected. // Read the tag to get the actual element count. WirePointer* tag = reinterpret_cast(ptr); KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE list with non-STRUCT elements not supported."); ptr += POINTER_SIZE_IN_WORDS; auto dataSize = tag->structRef.dataSize.get(); auto pointerCount = tag->structRef.ptrCount.get(); switch (elementSize) { case ElementSize::VOID: // Anything is a valid upgrade from Void. break; case ElementSize::BIT: KJ_FAIL_REQUIRE( "Schema mismatch: Found struct list where bit list was expected; upgrading boolean " "lists to structs is no longer supported.") { goto useDefault; } break; case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: KJ_REQUIRE(dataSize >= ONE * WORDS, "Schema mismatch: Existing list value is incompatible with expected type.") { goto useDefault; } break; case ElementSize::POINTER: KJ_REQUIRE(pointerCount >= ONE * POINTERS, "Schema mismatch: Existing list value is incompatible with expected type.") { goto useDefault; } // Adjust the pointer to point at the reference segment. ptr += dataSize; break; case ElementSize::INLINE_COMPOSITE: KJ_UNREACHABLE; } // OK, looks valid. return ListBuilder(segment, capTable, ptr, tag->structRef.wordSize() * BITS_PER_WORD / ELEMENTS, tag->inlineCompositeListElementCount(), dataSize * BITS_PER_WORD, pointerCount, ElementSize::INLINE_COMPOSITE); } else { auto dataSize = dataBitsPerElement(oldSize) * ELEMENTS; auto pointerCount = pointersPerElement(oldSize) * ELEMENTS; if (elementSize == ElementSize::BIT) { KJ_REQUIRE(oldSize == ElementSize::BIT, "Schema mismatch: Found non-bit list where bit list was expected.") { goto useDefault; } } else { KJ_REQUIRE(oldSize != ElementSize::BIT, "Schema mismatch: Found bit list where non-bit list was expected.") { goto useDefault; } KJ_REQUIRE(dataSize >= dataBitsPerElement(elementSize) * ELEMENTS, "Schema mismatch: Existing list value is incompatible with expected type.") { goto useDefault; } KJ_REQUIRE(pointerCount >= pointersPerElement(elementSize) * ELEMENTS, "Schema mismatch: Existing list value is incompatible with expected type.") { goto useDefault; } } auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; return ListBuilder(segment, capTable, ptr, step, ref->listRef.elementCount(), dataSize, pointerCount, oldSize); } } static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointerAnySize( WirePointer* origRef, SegmentBuilder* origSegment, CapTableBuilder* capTable, const word* defaultValue)) { return getWritableListPointerAnySize(origRef, origRef->target(), origSegment, capTable, defaultValue); } static KJ_ALWAYS_INLINE(ListBuilder getWritableListPointerAnySize( WirePointer* origRef, word* origRefTarget, SegmentBuilder* origSegment, CapTableBuilder* capTable, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { if (origRef->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return ListBuilder(ElementSize::VOID); } origRefTarget = copyMessage( origSegment, capTable, origRef, reinterpret_cast(defaultValue)); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } WirePointer* ref = origRef; SegmentBuilder* segment = origSegment; word* ptr = followFars(ref, origRefTarget, segment); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Called getWritableListPointerAnySize() but existing pointer is not a " "list.") { goto useDefault; } ElementSize elementSize = ref->listRef.elementSize(); if (elementSize == ElementSize::INLINE_COMPOSITE) { // Read the tag to get the actual element count. WirePointer* tag = reinterpret_cast(ptr); KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE list with non-STRUCT elements not supported."); ptr += POINTER_SIZE_IN_WORDS; return ListBuilder(segment, capTable, ptr, tag->structRef.wordSize() * BITS_PER_WORD / ELEMENTS, tag->inlineCompositeListElementCount(), tag->structRef.dataSize.get() * BITS_PER_WORD, tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE); } else { auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; return ListBuilder(segment, capTable, ptr, step, ref->listRef.elementCount(), dataSize, pointerCount, elementSize); } } static KJ_ALWAYS_INLINE(ListBuilder getWritableStructListPointer( WirePointer* origRef, SegmentBuilder* origSegment, CapTableBuilder* capTable, StructSize elementSize, const word* defaultValue)) { return getWritableStructListPointer(origRef, origRef->target(), origSegment, capTable, elementSize, defaultValue); } static KJ_ALWAYS_INLINE(ListBuilder getWritableStructListPointer( WirePointer* origRef, word* origRefTarget, SegmentBuilder* origSegment, CapTableBuilder* capTable, StructSize elementSize, const word* defaultValue, BuilderArena* orphanArena = nullptr)) { if (origRef->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return ListBuilder(ElementSize::INLINE_COMPOSITE); } origRefTarget = copyMessage( origSegment, capTable, origRef, reinterpret_cast(defaultValue)); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } // We must verify that the pointer has the right size and potentially upgrade it if not. WirePointer* oldRef = origRef; SegmentBuilder* oldSegment = origSegment; word* oldPtr = followFars(oldRef, origRefTarget, oldSegment); KJ_REQUIRE(oldRef->kind() == WirePointer::LIST, "Schema mismatch: Called getList{Field,Element}() but existing pointer is not a " "list.") { goto useDefault; } ElementSize oldSize = oldRef->listRef.elementSize(); if (oldSize == ElementSize::INLINE_COMPOSITE) { // Existing list is INLINE_COMPOSITE, but we need to verify that the sizes match. WirePointer* oldTag = reinterpret_cast(oldPtr); oldPtr += POINTER_SIZE_IN_WORDS; KJ_REQUIRE(oldTag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE list with non-STRUCT elements not supported.") { goto useDefault; } auto oldDataSize = oldTag->structRef.dataSize.get(); auto oldPointerCount = oldTag->structRef.ptrCount.get(); auto oldStep = (oldDataSize + oldPointerCount * WORDS_PER_POINTER) / ELEMENTS; auto elementCount = oldTag->inlineCompositeListElementCount(); if (oldDataSize >= elementSize.data && oldPointerCount >= elementSize.pointers) { // Old size is at least as large as we need. Ship it. return ListBuilder(oldSegment, capTable, oldPtr, oldStep * BITS_PER_WORD, elementCount, oldDataSize * BITS_PER_WORD, oldPointerCount, ElementSize::INLINE_COMPOSITE); } // The structs in this list are smaller than expected, probably written using an older // version of the protocol. We need to make a copy and expand them. auto newDataSize = kj::max(oldDataSize, elementSize.data); auto newPointerCount = kj::max(oldPointerCount, elementSize.pointers); auto newStep = (newDataSize + newPointerCount * WORDS_PER_POINTER) / ELEMENTS; auto totalSize = assertMax() - 1>( newStep * upgradeBound(elementCount), []() { KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size"); }); // Don't let allocate() zero out the object just yet. zeroPointerAndFars(origSegment, origRef); word* newPtr = allocate(origRef, origSegment, capTable, totalSize + POINTER_SIZE_IN_WORDS, WirePointer::LIST, orphanArena); origRef->listRef.setInlineComposite(totalSize); WirePointer* newTag = reinterpret_cast(newPtr); newTag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, elementCount); newTag->structRef.set(newDataSize, newPointerCount); newPtr += POINTER_SIZE_IN_WORDS; word* src = oldPtr; word* dst = newPtr; for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { // Copy data section. copyMemory(dst, src, oldDataSize); // Copy pointer section. WirePointer* newPointerSection = reinterpret_cast(dst + newDataSize); WirePointer* oldPointerSection = reinterpret_cast(src + oldDataSize); for (auto j: kj::zeroTo(oldPointerCount)) { transferPointer(origSegment, newPointerSection + j, oldSegment, oldPointerSection + j); } dst += newStep * (ONE * ELEMENTS); src += oldStep * (ONE * ELEMENTS); } auto oldSize = assertMax() - 1>( oldStep * upgradeBound(elementCount), []() { KJ_FAIL_ASSERT("old size overflows but new size doesn't?"); }); // Zero out old location. See explanation in getWritableStructPointer(). // Make sure to include the tag word. zeroMemory(oldPtr - POINTER_SIZE_IN_WORDS, oldSize + POINTER_SIZE_IN_WORDS); return ListBuilder(origSegment, capTable, newPtr, newStep * BITS_PER_WORD, elementCount, newDataSize * BITS_PER_WORD, newPointerCount, ElementSize::INLINE_COMPOSITE); } else { // We're upgrading from a non-struct list. auto oldDataSize = dataBitsPerElement(oldSize) * ELEMENTS; auto oldPointerCount = pointersPerElement(oldSize) * ELEMENTS; auto oldStep = (oldDataSize + oldPointerCount * BITS_PER_POINTER) / ELEMENTS; auto elementCount = oldRef->listRef.elementCount(); if (oldSize == ElementSize::VOID) { // Nothing to copy, just allocate a new list. return initStructListPointer(origRef, origSegment, capTable, elementCount, elementSize); } else { // Upgrading to an inline composite list. KJ_REQUIRE(oldSize != ElementSize::BIT, "Schema mismatch: Found bit list where struct list was expected; upgrading boolean " "lists to structs is no longer supported.") { goto useDefault; } auto newDataSize = elementSize.data; auto newPointerCount = elementSize.pointers; if (oldSize == ElementSize::POINTER) { newPointerCount = kj::max(newPointerCount, ONE * POINTERS); } else { // Old list contains data elements, so we need at least 1 word of data. newDataSize = kj::max(newDataSize, ONE * WORDS); } auto newStep = (newDataSize + newPointerCount * WORDS_PER_POINTER) / ELEMENTS; auto totalWords = assertMax() - 1>( newStep * upgradeBound(elementCount), []() {KJ_FAIL_REQUIRE("total size of struct list is larger than max segment size");}); // Don't let allocate() zero out the object just yet. zeroPointerAndFars(origSegment, origRef); word* newPtr = allocate(origRef, origSegment, capTable, totalWords + POINTER_SIZE_IN_WORDS, WirePointer::LIST, orphanArena); origRef->listRef.setInlineComposite(totalWords); WirePointer* tag = reinterpret_cast(newPtr); tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, elementCount); tag->structRef.set(newDataSize, newPointerCount); newPtr += POINTER_SIZE_IN_WORDS; if (oldSize == ElementSize::POINTER) { WirePointer* dst = reinterpret_cast(newPtr + newDataSize); WirePointer* src = reinterpret_cast(oldPtr); for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { transferPointer(origSegment, dst, oldSegment, src); dst += newStep / WORDS_PER_POINTER * (ONE * ELEMENTS); ++src; } } else { byte* dst = reinterpret_cast(newPtr); byte* src = reinterpret_cast(oldPtr); auto newByteStep = newStep * (ONE * ELEMENTS) * BYTES_PER_WORD; auto oldByteStep = oldDataSize / BITS_PER_BYTE; for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { copyMemory(dst, src, oldByteStep); src += oldByteStep; dst += newByteStep; } } auto oldSize = assertMax() - 1>( roundBitsUpToWords(oldStep * upgradeBound(elementCount)), []() { KJ_FAIL_ASSERT("old size overflows but new size doesn't?"); }); // Zero out old location. See explanation in getWritableStructPointer(). zeroMemory(oldPtr, oldSize); return ListBuilder(origSegment, capTable, newPtr, newStep * BITS_PER_WORD, elementCount, newDataSize * BITS_PER_WORD, newPointerCount, ElementSize::INLINE_COMPOSITE); } } } static KJ_ALWAYS_INLINE(SegmentAnd initTextPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, TextSize size, BuilderArena* orphanArena = nullptr)) { // The byte list must include a NUL terminator. auto byteSize = size + ONE * BYTES; // Allocate the space. word* ptr = allocate( ref, segment, capTable, roundBytesUpToWords(byteSize), WirePointer::LIST, orphanArena); // Initialize the pointer. ref->listRef.set(ElementSize::BYTE, byteSize * (ONE * ELEMENTS / BYTES)); // Build the Text::Builder. Note that since allocate()ed memory is pre-zero'd, we don't need // to initialize the NUL terminator. return { segment, Text::Builder(reinterpret_cast(ptr), unbound(size / BYTES)) }; } static KJ_ALWAYS_INLINE(SegmentAnd setTextPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, Text::Reader value, BuilderArena* orphanArena = nullptr)) { TextSize size = assertMax(bounded(value.size()), []() { KJ_FAIL_REQUIRE("text blob too big"); }) * BYTES; auto allocation = initTextPointer(ref, segment, capTable, size, orphanArena); copyMemory(allocation.value.begin(), value); return allocation; } static KJ_ALWAYS_INLINE(Text::Builder getWritableTextPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, const void* defaultValue, TextSize defaultSize)) { return getWritableTextPointer(ref, ref->target(), segment,capTable, defaultValue, defaultSize); } static KJ_ALWAYS_INLINE(Text::Builder getWritableTextPointer( WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable, const void* defaultValue, TextSize defaultSize)) { if (ref->isNull()) { useDefault: if (defaultSize == ZERO * BYTES) { return nullptr; } else { Text::Builder builder = initTextPointer(ref, segment, capTable, defaultSize).value; copyMemory(builder.asBytes().begin(), reinterpret_cast(defaultValue), defaultSize); return builder; } } else { word* ptr = followFars(ref, refTarget, segment); byte* bptr = reinterpret_cast(ptr); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Called getText{Field,Element}() but existing pointer is not a list.") { goto useDefault; } KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, "Schema mismatch: Called getText{Field,Element}() but existing list pointer is not " "byte-sized.") { goto useDefault; } auto maybeSize = trySubtract(ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS), ONE * BYTES); KJ_IF_MAYBE(size, maybeSize) { KJ_REQUIRE(*(bptr + *size) == '\0', "Text blob missing NUL terminator.") { goto useDefault; } return Text::Builder(reinterpret_cast(bptr), unbound(*size / BYTES)); } else { KJ_FAIL_REQUIRE("zero-size blob can't be text (need NUL terminator)") { goto useDefault; }; } } } static KJ_ALWAYS_INLINE(SegmentAnd initDataPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, BlobSize size, BuilderArena* orphanArena = nullptr)) { // Allocate the space. word* ptr = allocate(ref, segment, capTable, roundBytesUpToWords(size), WirePointer::LIST, orphanArena); // Initialize the pointer. ref->listRef.set(ElementSize::BYTE, size * (ONE * ELEMENTS / BYTES)); // Build the Data::Builder. return { segment, Data::Builder(reinterpret_cast(ptr), unbound(size / BYTES)) }; } static KJ_ALWAYS_INLINE(SegmentAnd setDataPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, Data::Reader value, BuilderArena* orphanArena = nullptr)) { BlobSize size = assertMaxBits(bounded(value.size()), []() { KJ_FAIL_REQUIRE("text blob too big"); }) * BYTES; auto allocation = initDataPointer(ref, segment, capTable, size, orphanArena); copyMemory(allocation.value.begin(), value); return allocation; } static KJ_ALWAYS_INLINE(Data::Builder getWritableDataPointer( WirePointer* ref, SegmentBuilder* segment, CapTableBuilder* capTable, const void* defaultValue, BlobSize defaultSize)) { return getWritableDataPointer(ref, ref->target(), segment, capTable, defaultValue, defaultSize); } static KJ_ALWAYS_INLINE(Data::Builder getWritableDataPointer( WirePointer* ref, word* refTarget, SegmentBuilder* segment, CapTableBuilder* capTable, const void* defaultValue, BlobSize defaultSize)) { if (ref->isNull()) { useDefault: if (defaultSize == ZERO * BYTES) { return nullptr; } else { Data::Builder builder = initDataPointer(ref, segment, capTable, defaultSize).value; copyMemory(builder.begin(), reinterpret_cast(defaultValue), defaultSize); return builder; } } else { word* ptr = followFars(ref, refTarget, segment); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Called getData{Field,Element}() but existing pointer is not a list.") { goto useDefault; } KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, "Schema mismatch: Called getData{Field,Element}() but existing list pointer is not " "byte-sized.") { goto useDefault; } return Data::Builder(reinterpret_cast(ptr), unbound(ref->listRef.elementCount() / ELEMENTS)); } } static SegmentAnd setStructPointer( SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref, StructReader value, BuilderArena* orphanArena = nullptr, bool canonical = false) { auto dataSize = roundBitsUpToBytes(value.dataSize); auto ptrCount = value.pointerCount; if (canonical) { // StructReaders should not have bitwidths other than 1, but let's be safe KJ_REQUIRE((value.dataSize == ONE * BITS) || (value.dataSize % BITS_PER_BYTE == ZERO * BITS)); if (value.dataSize == ONE * BITS) { // Handle the truncation case where it's a false in a 1-bit struct if (!value.getDataField(ZERO * ELEMENTS)) { dataSize = ZERO * BYTES; } } else { // Truncate the data section auto data = value.getDataSectionAsBlob(); auto end = data.end(); while (end > data.begin() && end[-1] == 0) --end; dataSize = intervalLength(data.begin(), end, MAX_STUCT_DATA_WORDS * BYTES_PER_WORD); } // Truncate pointer section const WirePointer* ptr = value.pointers + ptrCount; while (ptr > value.pointers && ptr[-1].isNull()) --ptr; ptrCount = intervalLength(value.pointers, ptr, MAX_STRUCT_POINTER_COUNT); } auto dataWords = roundBytesUpToWords(dataSize); auto totalSize = dataWords + ptrCount * WORDS_PER_POINTER; word* ptr = allocate(ref, segment, capTable, totalSize, WirePointer::STRUCT, orphanArena); ref->structRef.set(dataWords, ptrCount); if (value.dataSize == ONE * BITS) { // Data size could be made 0 by truncation if (dataSize != ZERO * BYTES) { *reinterpret_cast(ptr) = value.getDataField(ZERO * ELEMENTS); } } else { copyMemory(reinterpret_cast(ptr), reinterpret_cast(value.data), dataSize); } WirePointer* pointerSection = reinterpret_cast(ptr + dataWords); for (auto i: kj::zeroTo(ptrCount)) { copyPointer(segment, capTable, pointerSection + i, value.segment, value.capTable, value.pointers + i, value.nestingLimit, nullptr, canonical); } return { segment, ptr }; } #if !CAPNP_LITE static void setCapabilityPointer( SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref, kj::Own&& cap) { if (!ref->isNull()) { zeroObject(segment, capTable, ref); } if (cap->isNull()) { zeroMemory(ref); } else { ref->setCap(capTable->injectCap(kj::mv(cap))); } } #endif // !CAPNP_LITE static SegmentAnd setListPointer( SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref, ListReader value, BuilderArena* orphanArena = nullptr, bool canonical = false) { auto totalSize = assertMax() - 1>( roundBitsUpToWords(upgradeBound(value.elementCount) * value.step), []() { KJ_FAIL_ASSERT("encountered impossibly long struct list ListReader"); }); if (value.elementSize != ElementSize::INLINE_COMPOSITE) { // List of non-structs. word* ptr = allocate(ref, segment, capTable, totalSize, WirePointer::LIST, orphanArena); if (value.elementSize == ElementSize::POINTER) { // List of pointers. ref->listRef.set(ElementSize::POINTER, value.elementCount); for (auto i: kj::zeroTo(value.elementCount * (ONE * POINTERS / ELEMENTS))) { copyPointer(segment, capTable, reinterpret_cast(ptr) + i, value.segment, value.capTable, reinterpret_cast(value.ptr) + i, value.nestingLimit, nullptr, canonical); } } else { // List of data. ref->listRef.set(value.elementSize, value.elementCount); auto wholeByteSize = assertMax(MAX_SEGMENT_WORDS * BYTES_PER_WORD, upgradeBound(value.elementCount) * value.step / BITS_PER_BYTE, []() { KJ_FAIL_ASSERT("encountered impossibly long data ListReader"); }); copyMemory(reinterpret_cast(ptr), value.ptr, wholeByteSize); auto leftoverBits = (upgradeBound(value.elementCount) * value.step) % BITS_PER_BYTE; if (leftoverBits > ZERO * BITS) { // We need to copy a partial byte. uint8_t mask = (1 << unbound(leftoverBits / BITS)) - 1; *((reinterpret_cast(ptr)) + wholeByteSize) = mask & *(value.ptr + wholeByteSize); } } return { segment, ptr }; } else { // List of structs. StructDataWordCount declDataSize = value.structDataSize / BITS_PER_WORD; StructPointerCount declPointerCount = value.structPointerCount; StructDataWordCount dataSize = ZERO * WORDS; StructPointerCount ptrCount = ZERO * POINTERS; if (canonical) { for (auto i: kj::zeroTo(value.elementCount)) { auto element = value.getStructElement(i); // Truncate the data section auto data = element.getDataSectionAsBlob(); auto end = data.end(); while (end > data.begin() && end[-1] == 0) --end; dataSize = kj::max(dataSize, roundBytesUpToWords( intervalLength(data.begin(), end, MAX_STUCT_DATA_WORDS * BYTES_PER_WORD))); // Truncate pointer section const WirePointer* ptr = element.pointers + element.pointerCount; while (ptr > element.pointers && ptr[-1].isNull()) --ptr; ptrCount = kj::max(ptrCount, intervalLength(element.pointers, ptr, MAX_STRUCT_POINTER_COUNT)); } auto newTotalSize = (dataSize + upgradeBound(ptrCount) * WORDS_PER_POINTER) / ELEMENTS * value.elementCount; KJ_ASSERT(newTotalSize <= totalSize); // we've only removed data! totalSize = assumeMax() - 1>(newTotalSize); } else { dataSize = declDataSize; ptrCount = declPointerCount; } KJ_DASSERT(value.structDataSize % BITS_PER_WORD == ZERO * BITS); word* ptr = allocate(ref, segment, capTable, totalSize + POINTER_SIZE_IN_WORDS, WirePointer::LIST, orphanArena); ref->listRef.setInlineComposite(totalSize); WirePointer* tag = reinterpret_cast(ptr); tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, value.elementCount); tag->structRef.set(dataSize, ptrCount); word* dst = ptr + POINTER_SIZE_IN_WORDS; const word* src = reinterpret_cast(value.ptr); for (auto i KJ_UNUSED: kj::zeroTo(value.elementCount)) { copyMemory(dst, src, dataSize); dst += dataSize; src += declDataSize; for (auto j: kj::zeroTo(ptrCount)) { copyPointer(segment, capTable, reinterpret_cast(dst) + j, value.segment, value.capTable, reinterpret_cast(src) + j, value.nestingLimit, nullptr, canonical); } dst += ptrCount * WORDS_PER_POINTER; src += declPointerCount * WORDS_PER_POINTER; } return { segment, ptr }; } } static KJ_ALWAYS_INLINE(SegmentAnd copyPointer( SegmentBuilder* dstSegment, CapTableBuilder* dstCapTable, WirePointer* dst, SegmentReader* srcSegment, CapTableReader* srcCapTable, const WirePointer* src, int nestingLimit, BuilderArena* orphanArena = nullptr, bool canonical = false)) { return copyPointer(dstSegment, dstCapTable, dst, srcSegment, srcCapTable, src, src->target(srcSegment), nestingLimit, orphanArena, canonical); } static SegmentAnd copyPointer( SegmentBuilder* dstSegment, CapTableBuilder* dstCapTable, WirePointer* dst, SegmentReader* srcSegment, CapTableReader* srcCapTable, const WirePointer* src, const word* srcTarget, int nestingLimit, BuilderArena* orphanArena = nullptr, bool canonical = false) { // Deep-copy the object pointed to by src into dst. It turns out we can't reuse // readStructPointer(), etc. because they do type checking whereas here we want to accept any // valid pointer. if (src->isNull()) { useDefault: if (!dst->isNull()) { zeroObject(dstSegment, dstCapTable, dst); zeroMemory(dst); } return { dstSegment, nullptr }; } const word* ptr; KJ_IF_MAYBE(p, WireHelpers::followFars(src, srcTarget, srcSegment)) { ptr = p; } else { goto useDefault; } switch (src->kind()) { case WirePointer::STRUCT: KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { goto useDefault; } KJ_REQUIRE(boundsCheck(srcSegment, ptr, src->structRef.wordSize()), "Message contained out-of-bounds struct pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } return setStructPointer(dstSegment, dstCapTable, dst, StructReader(srcSegment, srcCapTable, ptr, reinterpret_cast(ptr + src->structRef.dataSize.get()), src->structRef.dataSize.get() * BITS_PER_WORD, src->structRef.ptrCount.get(), nestingLimit - 1), orphanArena, canonical); case WirePointer::LIST: { ElementSize elementSize = src->listRef.elementSize(); KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { goto useDefault; } if (elementSize == ElementSize::INLINE_COMPOSITE) { auto wordCount = src->listRef.inlineCompositeWordCount(); const WirePointer* tag = reinterpret_cast(ptr); KJ_REQUIRE(boundsCheck(srcSegment, ptr, wordCount + POINTER_SIZE_IN_WORDS), "Message contains out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } ptr += POINTER_SIZE_IN_WORDS; KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE lists of non-STRUCT type are not supported.") { goto useDefault; } auto elementCount = tag->inlineCompositeListElementCount(); auto wordsPerElement = tag->structRef.wordSize() / ELEMENTS; KJ_REQUIRE(wordsPerElement * upgradeBound(elementCount) <= wordCount, "INLINE_COMPOSITE list's elements overrun its word count.") { goto useDefault; } if (wordsPerElement * (ONE * ELEMENTS) == ZERO * WORDS) { // Watch out for lists of zero-sized structs, which can claim to be arbitrarily large // without having sent actual data. KJ_REQUIRE(amplifiedRead(srcSegment, elementCount * (ONE * WORDS / ELEMENTS)), "Message contains amplified list pointer.") { goto useDefault; } } return setListPointer(dstSegment, dstCapTable, dst, ListReader(srcSegment, srcCapTable, ptr, elementCount, wordsPerElement * BITS_PER_WORD, tag->structRef.dataSize.get() * BITS_PER_WORD, tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE, nestingLimit - 1), orphanArena, canonical); } else { auto dataSize = dataBitsPerElement(elementSize) * ELEMENTS; auto pointerCount = pointersPerElement(elementSize) * ELEMENTS; auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; auto elementCount = src->listRef.elementCount(); auto wordCount = roundBitsUpToWords(upgradeBound(elementCount) * step); KJ_REQUIRE(boundsCheck(srcSegment, ptr, wordCount), "Message contains out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } if (elementSize == ElementSize::VOID) { // Watch out for lists of void, which can claim to be arbitrarily large without having // sent actual data. KJ_REQUIRE(amplifiedRead(srcSegment, elementCount * (ONE * WORDS / ELEMENTS)), "Message contains amplified list pointer.") { goto useDefault; } } return setListPointer(dstSegment, dstCapTable, dst, ListReader(srcSegment, srcCapTable, ptr, elementCount, step, dataSize, pointerCount, elementSize, nestingLimit - 1), orphanArena, canonical); } } case WirePointer::FAR: KJ_FAIL_REQUIRE("Unexpected FAR pointer.") { goto useDefault; } case WirePointer::OTHER: { KJ_REQUIRE(src->isCapability(), "Unknown pointer type.") { goto useDefault; } if (canonical) { KJ_FAIL_REQUIRE("Cannot create a canonical message with a capability") { break; } } #if !CAPNP_LITE KJ_IF_MAYBE(cap, srcCapTable->extractCap(src->capRef.index.get())) { setCapabilityPointer(dstSegment, dstCapTable, dst, kj::mv(*cap)); // Return dummy non-null pointer so OrphanBuilder doesn't end up null. return { dstSegment, reinterpret_cast(1) }; } else { #endif // !CAPNP_LITE KJ_FAIL_REQUIRE("Message contained invalid capability pointer.") { goto useDefault; } #if !CAPNP_LITE } #endif // !CAPNP_LITE } } KJ_UNREACHABLE; } static void adopt(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref, OrphanBuilder&& value) { KJ_REQUIRE(value.segment == nullptr || value.segment->getArena() == segment->getArena(), "Adopted object must live in the same message."); if (!ref->isNull()) { zeroObject(segment, capTable, ref); } if (value == nullptr) { // Set null. zeroMemory(ref); } else if (value.tagAsPtr()->isPositional()) { WireHelpers::transferPointer(segment, ref, value.segment, value.tagAsPtr(), value.location); } else { // FAR and OTHER pointers are position-independent, so we can just copy. copyMemory(ref, value.tagAsPtr()); } // Take ownership away from the OrphanBuilder. zeroMemory(value.tagAsPtr()); value.location = nullptr; value.segment = nullptr; } static OrphanBuilder disown(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* ref) { word* location; if (ref->isNull()) { location = nullptr; } else if (ref->kind() == WirePointer::OTHER) { KJ_REQUIRE(ref->isCapability(), "Unknown pointer type.") { break; } location = reinterpret_cast(1); // dummy so that it is non-null } else { WirePointer* refCopy = ref; location = followFarsNoWritableCheck(refCopy, ref->target(), segment); } OrphanBuilder result(ref, segment, capTable, location); if (!ref->isNull() && ref->isPositional()) { result.tagAsPtr()->setKindForOrphan(ref->kind()); } // Zero out the pointer that was disowned. zeroMemory(ref); return result; } // ----------------------------------------------------------------- static KJ_ALWAYS_INLINE(StructReader readStructPointer( SegmentReader* segment, CapTableReader* capTable, const WirePointer* ref, const word* defaultValue, int nestingLimit)) { return readStructPointer(segment, capTable, ref, ref->target(segment), defaultValue, nestingLimit); } static KJ_ALWAYS_INLINE(StructReader readStructPointer( SegmentReader* segment, CapTableReader* capTable, const WirePointer* ref, const word* refTarget, const word* defaultValue, int nestingLimit)) { if (ref->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return StructReader(); } segment = nullptr; ref = reinterpret_cast(defaultValue); refTarget = ref->target(segment); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { goto useDefault; } const word* ptr; KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { ptr = p; } else { goto useDefault; } KJ_REQUIRE(ref->kind() == WirePointer::STRUCT, "Schema mismatch: Message contains non-struct pointer where struct pointer" "was expected.") { goto useDefault; } KJ_REQUIRE(boundsCheck(segment, ptr, ref->structRef.wordSize()), "Message contained out-of-bounds struct pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } return StructReader( segment, capTable, ptr, reinterpret_cast(ptr + ref->structRef.dataSize.get()), ref->structRef.dataSize.get() * BITS_PER_WORD, ref->structRef.ptrCount.get(), nestingLimit - 1); } #if !CAPNP_LITE static KJ_ALWAYS_INLINE(kj::Own readCapabilityPointer( SegmentReader* segment, CapTableReader* capTable, const WirePointer* ref, int nestingLimit)) { kj::Maybe> maybeCap; auto brokenCapFactory = readGlobalBrokenCapFactoryForLayoutCpp(); KJ_REQUIRE(brokenCapFactory != nullptr, "Trying to read capabilities without ever having created a capability context. " "To read capabilities from a message, you must imbue it with CapReaderContext, or " "use the Cap'n Proto RPC system."); if (ref->isNull()) { return brokenCapFactory->newNullCap(); } else if (!ref->isCapability()) { KJ_FAIL_REQUIRE( "Schema mismatch: Message contains non-capability pointer where capability pointer was " "expected.") { break; } return brokenCapFactory->newBrokenCap( "Calling capability extracted from a non-capability pointer."); } else KJ_IF_MAYBE(cap, capTable->extractCap(ref->capRef.index.get())) { return kj::mv(*cap); } else { KJ_FAIL_REQUIRE("Message contains invalid capability pointer.") { break; } return brokenCapFactory->newBrokenCap("Calling invalid capability pointer."); } } #endif // !CAPNP_LITE static KJ_ALWAYS_INLINE(ListReader readListPointer( SegmentReader* segment, CapTableReader* capTable, const WirePointer* ref, const word* defaultValue, ElementSize expectedElementSize, int nestingLimit, bool checkElementSize = true)) { return readListPointer(segment, capTable, ref, ref->target(segment), defaultValue, expectedElementSize, nestingLimit, checkElementSize); } static KJ_ALWAYS_INLINE(ListReader readListPointer( SegmentReader* segment, CapTableReader* capTable, const WirePointer* ref, const word* refTarget, const word* defaultValue, ElementSize expectedElementSize, int nestingLimit, bool checkElementSize = true)) { if (ref->isNull()) { useDefault: if (defaultValue == nullptr || reinterpret_cast(defaultValue)->isNull()) { return ListReader(expectedElementSize); } segment = nullptr; ref = reinterpret_cast(defaultValue); refTarget = ref->target(segment); defaultValue = nullptr; // If the default value is itself invalid, don't use it again. } KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { goto useDefault; } const word* ptr; KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { ptr = p; } else { goto useDefault; } KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Message contains non-list pointer where list pointer was " "expected.") { goto useDefault; } ElementSize elementSize = ref->listRef.elementSize(); if (elementSize == ElementSize::INLINE_COMPOSITE) { auto wordCount = ref->listRef.inlineCompositeWordCount(); // An INLINE_COMPOSITE list points to a tag, which is formatted like a pointer. const WirePointer* tag = reinterpret_cast(ptr); KJ_REQUIRE(boundsCheck(segment, ptr, wordCount + POINTER_SIZE_IN_WORDS), "Message contains out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } ptr += POINTER_SIZE_IN_WORDS; KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE lists of non-STRUCT type are not supported.") { goto useDefault; } auto size = tag->inlineCompositeListElementCount(); auto wordsPerElement = tag->structRef.wordSize() / ELEMENTS; KJ_REQUIRE(upgradeBound(size) * wordsPerElement <= wordCount, "INLINE_COMPOSITE list's elements overrun its word count.") { goto useDefault; } if (wordsPerElement * (ONE * ELEMENTS) == ZERO * WORDS) { // Watch out for lists of zero-sized structs, which can claim to be arbitrarily large // without having sent actual data. KJ_REQUIRE(amplifiedRead(segment, size * (ONE * WORDS / ELEMENTS)), "Message contains amplified list pointer.") { goto useDefault; } } if (checkElementSize) { // If a struct list was not expected, then presumably a non-struct list was upgraded to a // struct list. We need to manipulate the pointer to point at the first field of the // struct. Together with the `step` field, this will allow the struct list to be accessed // as if it were a primitive list without branching. // Check whether the size is compatible. switch (expectedElementSize) { case ElementSize::VOID: break; case ElementSize::BIT: KJ_FAIL_REQUIRE( "Found struct list where bit list was expected; upgrading boolean lists to structs " "is no longer supported.") { goto useDefault; } break; case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: KJ_REQUIRE(tag->structRef.dataSize.get() > ZERO * WORDS, "Schema mismatch: Expected a primitive list, but got a list of pointer-only " "structs.") { goto useDefault; } break; case ElementSize::POINTER: KJ_REQUIRE(tag->structRef.ptrCount.get() > ZERO * POINTERS, "Schema mismatch: Expected a pointer list, but got a list of data-only " "structs.") { goto useDefault; } break; case ElementSize::INLINE_COMPOSITE: break; } } return ListReader( segment, capTable, ptr, size, wordsPerElement * BITS_PER_WORD, tag->structRef.dataSize.get() * BITS_PER_WORD, tag->structRef.ptrCount.get(), ElementSize::INLINE_COMPOSITE, nestingLimit - 1); } else { // This is a primitive or pointer list, but all such lists can also be interpreted as struct // lists. We need to compute the data size and pointer count for such structs. auto dataSize = dataBitsPerElement(ref->listRef.elementSize()) * ELEMENTS; auto pointerCount = pointersPerElement(ref->listRef.elementSize()) * ELEMENTS; auto elementCount = ref->listRef.elementCount(); auto step = (dataSize + pointerCount * BITS_PER_POINTER) / ELEMENTS; auto wordCount = roundBitsUpToWords(upgradeBound(elementCount) * step); KJ_REQUIRE(boundsCheck(segment, ptr, wordCount), "Message contains out-of-bounds list pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } if (elementSize == ElementSize::VOID) { // Watch out for lists of void, which can claim to be arbitrarily large without having sent // actual data. KJ_REQUIRE(amplifiedRead(segment, elementCount * (ONE * WORDS / ELEMENTS)), "Message contains amplified list pointer.") { goto useDefault; } } if (checkElementSize) { if (elementSize == ElementSize::BIT && expectedElementSize != ElementSize::BIT) { KJ_FAIL_REQUIRE( "Found bit list where struct list was expected; upgrading boolean lists to structs " "is no longer supported.") { goto useDefault; } } // Verify that the elements are at least as large as the expected type. Note that if we // expected INLINE_COMPOSITE, the expected sizes here will be zero, because bounds checking // will be performed at field access time. So this check here is for the case where we // expected a list of some primitive or pointer type. BitCount expectedDataBitsPerElement = dataBitsPerElement(expectedElementSize) * ELEMENTS; WirePointerCount expectedPointersPerElement = pointersPerElement(expectedElementSize) * ELEMENTS; KJ_REQUIRE(expectedDataBitsPerElement <= dataSize, "Schema mismatch: Message contained list with incompatible element type.") { goto useDefault; } KJ_REQUIRE(expectedPointersPerElement <= pointerCount, "Schema mismatch: Message contained list with incompatible element type.") { goto useDefault; } } return ListReader(segment, capTable, ptr, elementCount, step, dataSize, pointerCount, elementSize, nestingLimit - 1); } } static KJ_ALWAYS_INLINE(Text::Reader readTextPointer( SegmentReader* segment, const WirePointer* ref, const void* defaultValue, ByteCount defaultSize)) { return readTextPointer(segment, ref, ref->target(segment), defaultValue, defaultSize); } static KJ_ALWAYS_INLINE(Text::Reader readTextPointer( SegmentReader* segment, const WirePointer* ref, const word* refTarget, const void* defaultValue, ByteCount defaultSize)) { if (ref->isNull()) { useDefault: if (defaultValue == nullptr) defaultValue = ""; return Text::Reader(reinterpret_cast(defaultValue), unbound(defaultSize / BYTES)); } else { const word* ptr; KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { ptr = p; } else { goto useDefault; } auto size = ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Message contains non-list pointer where text was expected.") { goto useDefault; } KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, "Schema mismatch: Message contains list pointer of non-bytes where text was " "expected.") { goto useDefault; } KJ_REQUIRE(boundsCheck(segment, ptr, roundBytesUpToWords(size)), "Message contained out-of-bounds text pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } KJ_REQUIRE(size > ZERO * BYTES, "Message contains text that is not NUL-terminated.") { goto useDefault; } const char* cptr = reinterpret_cast(ptr); uint unboundedSize = unbound(size / BYTES) - 1; KJ_REQUIRE(cptr[unboundedSize] == '\0', "Message contains text that is not NUL-terminated.") { goto useDefault; } return Text::Reader(cptr, unboundedSize); } } static KJ_ALWAYS_INLINE(Data::Reader readDataPointer( SegmentReader* segment, const WirePointer* ref, const void* defaultValue, BlobSize defaultSize)) { return readDataPointer(segment, ref, ref->target(segment), defaultValue, defaultSize); } static KJ_ALWAYS_INLINE(Data::Reader readDataPointer( SegmentReader* segment, const WirePointer* ref, const word* refTarget, const void* defaultValue, BlobSize defaultSize)) { if (ref->isNull()) { useDefault: return Data::Reader(reinterpret_cast(defaultValue), unbound(defaultSize / BYTES)); } else { const word* ptr; KJ_IF_MAYBE(p, followFars(ref, refTarget, segment)) { ptr = p; } else { goto useDefault; } if (KJ_UNLIKELY(ptr == nullptr)) { // Already reported error. goto useDefault; } auto size = ref->listRef.elementCount() * (ONE * BYTES / ELEMENTS); KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Message contains non-list pointer where data was expected.") { goto useDefault; } KJ_REQUIRE(ref->listRef.elementSize() == ElementSize::BYTE, "Schema mismatch: Message contains list pointer of non-bytes where data was " "expected.") { goto useDefault; } KJ_REQUIRE(boundsCheck(segment, ptr, roundBytesUpToWords(size)), "Message contained out-of-bounds data pointer. " OUT_OF_BOUNDS_ERROR_DETAIL) { goto useDefault; } return Data::Reader(reinterpret_cast(ptr), unbound(size / BYTES)); } } }; // ======================================================================================= // PointerBuilder StructBuilder PointerBuilder::initStruct(StructSize size) { return WireHelpers::initStructPointer(pointer, segment, capTable, size); } StructBuilder PointerBuilder::getStruct(StructSize size, const word* defaultValue) { return WireHelpers::getWritableStructPointer(pointer, segment, capTable, size, defaultValue); } ListBuilder PointerBuilder::initList(ElementSize elementSize, ElementCount elementCount) { return WireHelpers::initListPointer(pointer, segment, capTable, elementCount, elementSize); } ListBuilder PointerBuilder::initStructList(ElementCount elementCount, StructSize elementSize) { return WireHelpers::initStructListPointer(pointer, segment, capTable, elementCount, elementSize); } ListBuilder PointerBuilder::getList(ElementSize elementSize, const word* defaultValue) { return WireHelpers::getWritableListPointer(pointer, segment, capTable, elementSize, defaultValue); } ListBuilder PointerBuilder::getStructList(StructSize elementSize, const word* defaultValue) { return WireHelpers::getWritableStructListPointer( pointer, segment, capTable, elementSize, defaultValue); } ListBuilder PointerBuilder::getListAnySize(const word* defaultValue) { return WireHelpers::getWritableListPointerAnySize(pointer, segment, capTable, defaultValue); } template <> Text::Builder PointerBuilder::initBlob(ByteCount size) { return WireHelpers::initTextPointer(pointer, segment, capTable, assertMax(size, ThrowOverflow())).value; } template <> void PointerBuilder::setBlob(Text::Reader value) { WireHelpers::setTextPointer(pointer, segment, capTable, value); } template <> Text::Builder PointerBuilder::getBlob(const void* defaultValue, ByteCount defaultSize) { return WireHelpers::getWritableTextPointer(pointer, segment, capTable, defaultValue, assertMax(defaultSize, ThrowOverflow())); } template <> Data::Builder PointerBuilder::initBlob(ByteCount size) { return WireHelpers::initDataPointer(pointer, segment, capTable, assertMaxBits(size, ThrowOverflow())).value; } template <> void PointerBuilder::setBlob(Data::Reader value) { WireHelpers::setDataPointer(pointer, segment, capTable, value); } template <> Data::Builder PointerBuilder::getBlob(const void* defaultValue, ByteCount defaultSize) { return WireHelpers::getWritableDataPointer(pointer, segment, capTable, defaultValue, assertMaxBits(defaultSize, ThrowOverflow())); } void PointerBuilder::setStruct(const StructReader& value, bool canonical) { WireHelpers::setStructPointer(segment, capTable, pointer, value, nullptr, canonical); } void PointerBuilder::setList(const ListReader& value, bool canonical) { WireHelpers::setListPointer(segment, capTable, pointer, value, nullptr, canonical); } #if !CAPNP_LITE kj::Own PointerBuilder::getCapability() { return WireHelpers::readCapabilityPointer( segment, capTable, pointer, kj::maxValue); } void PointerBuilder::setCapability(kj::Own&& cap) { WireHelpers::setCapabilityPointer(segment, capTable, pointer, kj::mv(cap)); } #endif // !CAPNP_LITE void PointerBuilder::adopt(OrphanBuilder&& value) { WireHelpers::adopt(segment, capTable, pointer, kj::mv(value)); } OrphanBuilder PointerBuilder::disown() { return WireHelpers::disown(segment, capTable, pointer); } void PointerBuilder::clear() { WireHelpers::zeroObject(segment, capTable, pointer); WireHelpers::zeroMemory(pointer); } PointerType PointerBuilder::getPointerType() const { if(pointer->isNull()) { return PointerType::NULL_; } else { WirePointer* ptr = pointer; SegmentBuilder* sgmt = segment; WireHelpers::followFars(ptr, ptr->target(), sgmt); switch(ptr->kind()) { case WirePointer::FAR: KJ_FAIL_ASSERT("far pointer not followed?"); case WirePointer::STRUCT: return PointerType::STRUCT; case WirePointer::LIST: return PointerType::LIST; case WirePointer::OTHER: KJ_REQUIRE(ptr->isCapability(), "unknown pointer type"); return PointerType::CAPABILITY; } KJ_UNREACHABLE; } } void PointerBuilder::transferFrom(PointerBuilder other) { if (!pointer->isNull()) { WireHelpers::zeroObject(segment, capTable, pointer); WireHelpers::zeroMemory(pointer); } WireHelpers::transferPointer(segment, pointer, other.segment, other.pointer); WireHelpers::zeroMemory(other.pointer); } void PointerBuilder::copyFrom(PointerReader other, bool canonical) { if (other.pointer == nullptr) { if (!pointer->isNull()) { WireHelpers::zeroObject(segment, capTable, pointer); WireHelpers::zeroMemory(pointer); } } else { WireHelpers::copyPointer(segment, capTable, pointer, other.segment, other.capTable, other.pointer, other.nestingLimit, nullptr, canonical); } } PointerReader PointerBuilder::asReader() const { return PointerReader(segment, capTable, pointer, kj::maxValue); } BuilderArena* PointerBuilder::getArena() const { return segment->getArena(); } CapTableBuilder* PointerBuilder::getCapTable() { return capTable; } PointerBuilder PointerBuilder::imbue(CapTableBuilder* capTable) { auto result = *this; result.capTable = capTable; return result; } // ======================================================================================= // PointerReader PointerReader PointerReader::getRoot(SegmentReader* segment, CapTableReader* capTable, const word* location, int nestingLimit) { KJ_REQUIRE(WireHelpers::boundsCheck(segment, location, POINTER_SIZE_IN_WORDS), "Root location out-of-bounds.") { location = nullptr; } return PointerReader(segment, capTable, reinterpret_cast(location), nestingLimit); } StructReader PointerReader::getStruct(const word* defaultValue) const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readStructPointer(segment, capTable, ref, defaultValue, nestingLimit); } ListReader PointerReader::getList(ElementSize expectedElementSize, const word* defaultValue) const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readListPointer( segment, capTable, ref, defaultValue, expectedElementSize, nestingLimit); } ListReader PointerReader::getListAnySize(const word* defaultValue) const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readListPointer( segment, capTable, ref, defaultValue, ElementSize::VOID /* dummy */, nestingLimit, false); } template <> Text::Reader PointerReader::getBlob(const void* defaultValue, ByteCount defaultSize) const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readTextPointer(segment, ref, defaultValue, defaultSize); } template <> Data::Reader PointerReader::getBlob(const void* defaultValue, ByteCount defaultSize) const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readDataPointer(segment, ref, defaultValue, assertMaxBits(defaultSize, ThrowOverflow())); } #if !CAPNP_LITE kj::Own PointerReader::getCapability() const { const WirePointer* ref = pointer == nullptr ? &zero.pointer : pointer; return WireHelpers::readCapabilityPointer(segment, capTable, ref, nestingLimit); } #endif // !CAPNP_LITE const word* PointerReader::getUnchecked() const { KJ_REQUIRE(segment == nullptr, "getUncheckedPointer() only allowed on unchecked messages."); return reinterpret_cast(pointer); } MessageSizeCounts PointerReader::targetSize() const { return pointer == nullptr ? MessageSizeCounts { ZERO * WORDS, 0 } : WireHelpers::totalSize(segment, pointer, nestingLimit); } PointerType PointerReader::getPointerType() const { if(pointer == nullptr || pointer->isNull()) { return PointerType::NULL_; } else { const WirePointer* ptr = pointer; const word* refTarget = ptr->target(segment); SegmentReader* sgmt = segment; if (WireHelpers::followFars(ptr, refTarget, sgmt) == nullptr) return PointerType::NULL_; switch(ptr->kind()) { case WirePointer::FAR: KJ_FAIL_ASSERT("far pointer not followed?") { return PointerType::NULL_; } case WirePointer::STRUCT: return PointerType::STRUCT; case WirePointer::LIST: return PointerType::LIST; case WirePointer::OTHER: KJ_REQUIRE(ptr->isCapability(), "unknown pointer type") { return PointerType::NULL_; } return PointerType::CAPABILITY; } KJ_UNREACHABLE; } } kj::Maybe PointerReader::getArena() const { return segment == nullptr ? nullptr : segment->getArena(); } CapTableReader* PointerReader::getCapTable() { return capTable; } PointerReader PointerReader::imbue(CapTableReader* capTable) const { auto result = *this; result.capTable = capTable; return result; } bool PointerReader::isCanonical(const word **readHead) { if (!this->pointer) { // The pointer is null, so we are canonical and do not read return true; } if (!this->pointer->isPositional()) { // The pointer is a FAR or OTHER pointer, and is non-canonical return false; } switch (this->getPointerType()) { case PointerType::NULL_: // The pointer is null, we are canonical and do not read return true; case PointerType::STRUCT: { bool dataTrunc = false, ptrTrunc = false; auto structReader = this->getStruct(nullptr); if (structReader.getDataSectionSize() == ZERO * BITS && structReader.getPointerSectionSize() == ZERO * POINTERS) { return reinterpret_cast(this->pointer) == structReader.getLocation(); } else { // Fun fact: Once this call to isCanonical() returns, Clang may re-order the evaluation of // the && operators. In theory this is wrong because && is short-circuiting, but Clang // apparently sees that there are no side effects to the right of &&, so decides it is // safe to skip short-circuiting. It turns out, though, this is observable under // valgrind: if we don't initialize `dataTrunc` when declaring it above, then valgrind // reports "Conditional jump or move depends on uninitialised value(s)". Specifically // this happens in cases where structReader.isCanonical() returns false -- it is allowed // to skip initializing `dataTrunc` in that case. The short-circuiting && should mean // that we don't read `dataTrunc` in that case, except Clang's optimizations. Ultimately // the uninitialized read is fine because eventually the whole expression evaluates false // either way. But, to make valgrind happy, we initialize the bools above... return structReader.isCanonical(readHead, readHead, &dataTrunc, &ptrTrunc) && dataTrunc && ptrTrunc; } } case PointerType::LIST: return this->getListAnySize(nullptr).isCanonical(readHead, pointer); case PointerType::CAPABILITY: KJ_FAIL_ASSERT("Capabilities are not positional"); } KJ_UNREACHABLE; } // ======================================================================================= // StructBuilder void StructBuilder::clearAll() { if (dataSize == ONE * BITS) { setDataField(ONE * ELEMENTS, false); } else { WireHelpers::zeroMemory(reinterpret_cast(data), dataSize / BITS_PER_BYTE); } for (auto i: kj::zeroTo(pointerCount)) { WireHelpers::zeroObject(segment, capTable, pointers + i); } WireHelpers::zeroMemory(pointers, pointerCount); } void StructBuilder::transferContentFrom(StructBuilder other) { // Determine the amount of data the builders have in common. auto sharedDataSize = kj::min(dataSize, other.dataSize); if (dataSize > sharedDataSize) { // Since the target is larger than the source, make sure to zero out the extra bits that the // source doesn't have. if (dataSize == ONE * BITS) { setDataField(ZERO * ELEMENTS, false); } else { byte* unshared = reinterpret_cast(data) + sharedDataSize / BITS_PER_BYTE; // Note: this subtraction can't fail due to the if() above WireHelpers::zeroMemory(unshared, subtractChecked(dataSize, sharedDataSize, []() {}) / BITS_PER_BYTE); } } // Copy over the shared part. if (sharedDataSize == ONE * BITS) { setDataField(ZERO * ELEMENTS, other.getDataField(ZERO * ELEMENTS)); } else { WireHelpers::copyMemory(reinterpret_cast(data), reinterpret_cast(other.data), sharedDataSize / BITS_PER_BYTE); } // Zero out all pointers in the target. for (auto i: kj::zeroTo(pointerCount)) { WireHelpers::zeroObject(segment, capTable, pointers + i); } WireHelpers::zeroMemory(pointers, pointerCount); // Transfer the pointers. auto sharedPointerCount = kj::min(pointerCount, other.pointerCount); for (auto i: kj::zeroTo(sharedPointerCount)) { WireHelpers::transferPointer(segment, pointers + i, other.segment, other.pointers + i); } // Zero out the pointers that were transferred in the source because it no longer has ownership. // If the source had any extra pointers that the destination didn't have space for, we // intentionally leave them be, so that they'll be cleaned up later. WireHelpers::zeroMemory(other.pointers, sharedPointerCount); } void StructBuilder::copyContentFrom(StructReader other) { // Determine the amount of data the builders have in common. auto sharedDataSize = kj::min(dataSize, other.dataSize); auto sharedPointerCount = kj::min(pointerCount, other.pointerCount); if ((sharedDataSize > ZERO * BITS && other.data == data) || (sharedPointerCount > ZERO * POINTERS && other.pointers == pointers)) { // At least one of the section pointers is pointing to ourself. Verify that the other is two // (but ignore empty sections). KJ_ASSERT((sharedDataSize == ZERO * BITS || other.data == data) && (sharedPointerCount == ZERO * POINTERS || other.pointers == pointers)); // So `other` appears to be a reader for this same struct. No coping is needed. return; } if (dataSize > sharedDataSize) { // Since the target is larger than the source, make sure to zero out the extra bits that the // source doesn't have. if (dataSize == ONE * BITS) { setDataField(ZERO * ELEMENTS, false); } else { byte* unshared = reinterpret_cast(data) + sharedDataSize / BITS_PER_BYTE; WireHelpers::zeroMemory(unshared, subtractChecked(dataSize, sharedDataSize, []() {}) / BITS_PER_BYTE); } } // Copy over the shared part. if (sharedDataSize == ONE * BITS) { setDataField(ZERO * ELEMENTS, other.getDataField(ZERO * ELEMENTS)); } else { WireHelpers::copyMemory(reinterpret_cast(data), reinterpret_cast(other.data), sharedDataSize / BITS_PER_BYTE); } // Zero out all pointers in the target. for (auto i: kj::zeroTo(pointerCount)) { WireHelpers::zeroObject(segment, capTable, pointers + i); } WireHelpers::zeroMemory(pointers, pointerCount); // Copy the pointers. for (auto i: kj::zeroTo(sharedPointerCount)) { WireHelpers::copyPointer(segment, capTable, pointers + i, other.segment, other.capTable, other.pointers + i, other.nestingLimit); } } StructReader StructBuilder::asReader() const { return StructReader(segment, capTable, data, pointers, dataSize, pointerCount, kj::maxValue); } BuilderArena* StructBuilder::getArena() { return segment->getArena(); } CapTableBuilder* StructBuilder::getCapTable() { return capTable; } StructBuilder StructBuilder::imbue(CapTableBuilder* capTable) { auto result = *this; result.capTable = capTable; return result; } // ======================================================================================= // StructReader MessageSizeCounts StructReader::totalSize() const { MessageSizeCounts result = { WireHelpers::roundBitsUpToWords(dataSize) + pointerCount * WORDS_PER_POINTER, 0 }; for (auto i: kj::zeroTo(pointerCount)) { result += WireHelpers::totalSize(segment, pointers + i, nestingLimit); } if (segment != nullptr) { // This traversal should not count against the read limit, because it's highly likely that // the caller is going to traverse the object again, e.g. to copy it. segment->unread(result.wordCount); } return result; } kj::Array StructReader::canonicalize() { auto size = totalSize().wordCount + POINTER_SIZE_IN_WORDS; kj::Array backing = kj::heapArray(unbound(size / WORDS)); WireHelpers::zeroMemory(backing.asPtr()); FlatMessageBuilder builder(backing); _::PointerHelpers::getInternalBuilder(builder.initRoot()).setStruct(*this, true); KJ_ASSERT(builder.isCanonical()); auto output = builder.getSegmentsForOutput()[0]; kj::Array trunc = kj::heapArray(output.size()); WireHelpers::copyMemory(trunc.begin(), output); return trunc; } CapTableReader* StructReader::getCapTable() { return capTable; } StructReader StructReader::imbue(CapTableReader* capTable) const { auto result = *this; result.capTable = capTable; return result; } bool StructReader::isCanonical(const word **readHead, const word **ptrHead, bool *dataTrunc, bool *ptrTrunc) { if (this->getLocation() != *readHead) { // Our target area is not at the readHead, preorder fails return false; } if (this->getDataSectionSize() % BITS_PER_WORD != ZERO * BITS) { // Using legacy non-word-size structs, reject return false; } auto dataSize = this->getDataSectionSize() / BITS_PER_WORD; // Mark whether the struct is properly truncated KJ_IF_MAYBE(diff, trySubtract(dataSize, ONE * WORDS)) { *dataTrunc = this->getDataField(*diff / WORDS * ELEMENTS) != 0; } else { // Data segment empty. *dataTrunc = true; } KJ_IF_MAYBE(diff, trySubtract(this->pointerCount, ONE * POINTERS)) { *ptrTrunc = !this->getPointerField(*diff).isNull(); } else { *ptrTrunc = true; } // Advance the read head *readHead += (dataSize + (this->pointerCount * WORDS_PER_POINTER)); // Check each pointer field for canonicity for (auto ptrIndex: kj::zeroTo(this->pointerCount)) { if (!this->getPointerField(ptrIndex).isCanonical(ptrHead)) { return false; } } return true; } // ======================================================================================= // ListBuilder Text::Builder ListBuilder::asText() { KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, "Expected Text, got list of non-bytes.") { return Text::Builder(); } size_t size = unbound(elementCount / ELEMENTS); KJ_REQUIRE(size > 0, "Message contains text that is not NUL-terminated.") { return Text::Builder(); } char* cptr = reinterpret_cast(ptr); --size; // NUL terminator KJ_REQUIRE(cptr[size] == '\0', "Message contains text that is not NUL-terminated.") { return Text::Builder(); } return Text::Builder(cptr, size); } Data::Builder ListBuilder::asData() { KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, "Expected Text, got list of non-bytes.") { return Data::Builder(); } return Data::Builder(reinterpret_cast(ptr), unbound(elementCount / ELEMENTS)); } StructBuilder ListBuilder::getStructElement(ElementCount index) { auto indexBit = upgradeBound(index) * step; byte* structData = ptr + indexBit / BITS_PER_BYTE; KJ_DASSERT(indexBit % BITS_PER_BYTE == ZERO * BITS); return StructBuilder(segment, capTable, structData, reinterpret_cast(structData + structDataSize / BITS_PER_BYTE), structDataSize, structPointerCount); } ListReader ListBuilder::asReader() const { return ListReader(segment, capTable, ptr, elementCount, step, structDataSize, structPointerCount, elementSize, kj::maxValue); } BuilderArena* ListBuilder::getArena() { return segment->getArena(); } CapTableBuilder* ListBuilder::getCapTable() { return capTable; } ListBuilder ListBuilder::imbue(CapTableBuilder* capTable) { auto result = *this; result.capTable = capTable; return result; } // ======================================================================================= // ListReader Text::Reader ListReader::asText() { KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, "Schema mismatch: Expected Text, got list of non-bytes.") { return Text::Reader(); } size_t size = unbound(elementCount / ELEMENTS); KJ_REQUIRE(size > 0, "Message contains text that is not NUL-terminated.") { return Text::Reader(); } const char* cptr = reinterpret_cast(ptr); --size; // NUL terminator KJ_REQUIRE(cptr[size] == '\0', "Message contains text that is not NUL-terminated.") { return Text::Reader(); } return Text::Reader(cptr, size); } Data::Reader ListReader::asData() { KJ_REQUIRE(structDataSize == G(8) * BITS && structPointerCount == ZERO * POINTERS, "Schema mismatch: Expected Text, got list of non-bytes.") { return Data::Reader(); } return Data::Reader(reinterpret_cast(ptr), unbound(elementCount / ELEMENTS)); } kj::ArrayPtr ListReader::asRawBytes() const { KJ_REQUIRE(structPointerCount == ZERO * POINTERS, "Schema mismatch: Expected data only, got pointers.") { return kj::ArrayPtr(); } return arrayPtr(reinterpret_cast(ptr), WireHelpers::roundBitsUpToBytes( upgradeBound(elementCount) * (structDataSize / ELEMENTS))); } StructReader ListReader::getStructElement(ElementCount index) const { KJ_REQUIRE(nestingLimit > 0, "Message is too deeply-nested or contains cycles. See capnp::ReaderOptions.") { return StructReader(); } auto indexBit = upgradeBound(index) * step; const byte* structData = ptr + indexBit / BITS_PER_BYTE; const WirePointer* structPointers = reinterpret_cast(structData + structDataSize / BITS_PER_BYTE); KJ_DASSERT(indexBit % BITS_PER_BYTE == ZERO * BITS); return StructReader( segment, capTable, structData, structPointers, structDataSize, structPointerCount, nestingLimit - 1); } MessageSizeCounts ListReader::totalSize() const { // TODO(cleanup): This is kind of a lot of logic duplicated from WireHelpers::totalSize(), but // it's unclear how to share it effectively. MessageSizeCounts result = { ZERO * WORDS, 0 }; switch (elementSize) { case ElementSize::VOID: // Nothing. break; case ElementSize::BIT: case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: result.addWords(WireHelpers::roundBitsUpToWords( upgradeBound(elementCount) * dataBitsPerElement(elementSize))); break; case ElementSize::POINTER: { auto count = elementCount * (POINTERS / ELEMENTS); result.addWords(count * WORDS_PER_POINTER); for (auto i: kj::zeroTo(count)) { result += WireHelpers::totalSize(segment, reinterpret_cast(ptr) + i, nestingLimit); } break; } case ElementSize::INLINE_COMPOSITE: { // Don't forget to count the tag word. auto wordSize = upgradeBound(elementCount) * step / BITS_PER_WORD; result.addWords(wordSize + POINTER_SIZE_IN_WORDS); if (structPointerCount > ZERO * POINTERS) { const word* pos = reinterpret_cast(ptr); for (auto i KJ_UNUSED: kj::zeroTo(elementCount)) { pos += structDataSize / BITS_PER_WORD; for (auto j KJ_UNUSED: kj::zeroTo(structPointerCount)) { result += WireHelpers::totalSize(segment, reinterpret_cast(pos), nestingLimit); pos += POINTER_SIZE_IN_WORDS; } } } break; } } if (segment != nullptr) { // This traversal should not count against the read limit, because it's highly likely that // the caller is going to traverse the object again, e.g. to copy it. segment->unread(result.wordCount); } return result; } CapTableReader* ListReader::getCapTable() { return capTable; } ListReader ListReader::imbue(CapTableReader* capTable) const { auto result = *this; result.capTable = capTable; return result; } bool ListReader::isCanonical(const word **readHead, const WirePointer *ref) { switch (this->getElementSize()) { case ElementSize::INLINE_COMPOSITE: { *readHead += 1; if (reinterpret_cast(this->ptr) != *readHead) { // The next word to read is the tag word, but the pointer is in // front of it, so our check is slightly different return false; } if (this->structDataSize % BITS_PER_WORD != ZERO * BITS) { return false; } auto elementSize = StructSize(this->structDataSize / BITS_PER_WORD, this->structPointerCount).total() / ELEMENTS; auto totalSize = upgradeBound(this->elementCount) * elementSize; if (totalSize != ref->listRef.inlineCompositeWordCount()) { return false; } if (elementSize == ZERO * WORDS / ELEMENTS) { return true; } auto listEnd = *readHead + totalSize; auto pointerHead = listEnd; bool listDataTrunc = false; bool listPtrTrunc = false; for (auto ec: kj::zeroTo(this->elementCount)) { bool dataTrunc, ptrTrunc; if (!this->getStructElement(ec).isCanonical(readHead, &pointerHead, &dataTrunc, &ptrTrunc)) { return false; } listDataTrunc |= dataTrunc; listPtrTrunc |= ptrTrunc; } KJ_REQUIRE(*readHead == listEnd, *readHead, listEnd); *readHead = pointerHead; return listDataTrunc && listPtrTrunc; } case ElementSize::POINTER: { if (reinterpret_cast(this->ptr) != *readHead) { return false; } *readHead += this->elementCount * (POINTERS / ELEMENTS) * WORDS_PER_POINTER; for (auto ec: kj::zeroTo(this->elementCount)) { if (!this->getPointerElement(ec).isCanonical(readHead)) { return false; } } return true; } default: { if (reinterpret_cast(this->ptr) != *readHead) { return false; } auto bitSize = upgradeBound(this->elementCount) * dataBitsPerElement(this->elementSize); auto truncatedByteSize = bitSize / BITS_PER_BYTE; auto byteReadHead = reinterpret_cast(*readHead) + truncatedByteSize; auto readHeadEnd = *readHead + WireHelpers::roundBitsUpToWords(bitSize); auto leftoverBits = bitSize % BITS_PER_BYTE; if (leftoverBits > ZERO * BITS) { auto mask = ~((1 << unbound(leftoverBits / BITS)) - 1); if (mask & *byteReadHead) { return false; } byteReadHead += 1; } while (byteReadHead != reinterpret_cast(readHeadEnd)) { if (*byteReadHead != 0) { return false; } byteReadHead += 1; } *readHead = readHeadEnd; return true; } } KJ_UNREACHABLE; } // ======================================================================================= // OrphanBuilder OrphanBuilder OrphanBuilder::initStruct( BuilderArena* arena, CapTableBuilder* capTable, StructSize size) { OrphanBuilder result; StructBuilder builder = WireHelpers::initStructPointer( result.tagAsPtr(), nullptr, capTable, size, arena); result.segment = builder.segment; result.capTable = capTable; result.location = builder.getLocation(); return result; } OrphanBuilder OrphanBuilder::initList( BuilderArena* arena, CapTableBuilder* capTable, ElementCount elementCount, ElementSize elementSize) { OrphanBuilder result; ListBuilder builder = WireHelpers::initListPointer( result.tagAsPtr(), nullptr, capTable, elementCount, elementSize, arena); result.segment = builder.segment; result.capTable = capTable; result.location = builder.getLocation(); return result; } OrphanBuilder OrphanBuilder::initStructList( BuilderArena* arena, CapTableBuilder* capTable, ElementCount elementCount, StructSize elementSize) { OrphanBuilder result; ListBuilder builder = WireHelpers::initStructListPointer( result.tagAsPtr(), nullptr, capTable, elementCount, elementSize, arena); result.segment = builder.segment; result.capTable = capTable; result.location = builder.getLocation(); return result; } OrphanBuilder OrphanBuilder::initText( BuilderArena* arena, CapTableBuilder* capTable, ByteCount size) { OrphanBuilder result; auto allocation = WireHelpers::initTextPointer(result.tagAsPtr(), nullptr, capTable, assertMax(size, ThrowOverflow()), arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value.begin()); return result; } OrphanBuilder OrphanBuilder::initData( BuilderArena* arena, CapTableBuilder* capTable, ByteCount size) { OrphanBuilder result; auto allocation = WireHelpers::initDataPointer(result.tagAsPtr(), nullptr, capTable, assertMaxBits(size), arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value.begin()); return result; } OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, StructReader copyFrom) { OrphanBuilder result; auto allocation = WireHelpers::setStructPointer( nullptr, capTable, result.tagAsPtr(), copyFrom, arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value); return result; } OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, ListReader copyFrom) { OrphanBuilder result; auto allocation = WireHelpers::setListPointer( nullptr, capTable, result.tagAsPtr(), copyFrom, arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value); return result; } OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, PointerReader copyFrom) { OrphanBuilder result; auto allocation = WireHelpers::copyPointer( nullptr, capTable, result.tagAsPtr(), copyFrom.segment, copyFrom.capTable, copyFrom.pointer, copyFrom.nestingLimit, arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value); return result; } OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, Text::Reader copyFrom) { OrphanBuilder result; auto allocation = WireHelpers::setTextPointer( result.tagAsPtr(), nullptr, capTable, copyFrom, arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value.begin()); return result; } OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, Data::Reader copyFrom) { OrphanBuilder result; auto allocation = WireHelpers::setDataPointer( result.tagAsPtr(), nullptr, capTable, copyFrom, arena); result.segment = allocation.segment; result.capTable = capTable; result.location = reinterpret_cast(allocation.value.begin()); return result; } #if !CAPNP_LITE OrphanBuilder OrphanBuilder::copy( BuilderArena* arena, CapTableBuilder* capTable, kj::Own copyFrom) { OrphanBuilder result; WireHelpers::setCapabilityPointer(nullptr, capTable, result.tagAsPtr(), kj::mv(copyFrom)); result.segment = arena->getSegment(SegmentId(0)); result.capTable = capTable; result.location = &result.tag; // dummy to make location non-null return result; } #endif // !CAPNP_LITE OrphanBuilder OrphanBuilder::concat( BuilderArena* arena, CapTableBuilder* capTable, ElementSize elementSize, StructSize structSize, kj::ArrayPtr lists) { KJ_REQUIRE(lists.size() > 0, "Can't concat empty list "); // Find the overall element count and size. ListElementCount elementCount = ZERO * ELEMENTS; for (auto& list: lists) { elementCount = assertMaxBits(elementCount + list.elementCount, []() { KJ_FAIL_REQUIRE("concatenated list exceeds list size limit"); }); if (list.elementSize != elementSize) { // If element sizes don't all match, upgrade to struct list. KJ_REQUIRE(list.elementSize != ElementSize::BIT && elementSize != ElementSize::BIT, "can't upgrade bit lists to struct lists"); elementSize = ElementSize::INLINE_COMPOSITE; } structSize.data = kj::max(structSize.data, WireHelpers::roundBitsUpToWords(list.structDataSize)); structSize.pointers = kj::max(structSize.pointers, list.structPointerCount); } // Allocate the list. OrphanBuilder result; ListBuilder builder = (elementSize == ElementSize::INLINE_COMPOSITE) ? WireHelpers::initStructListPointer( result.tagAsPtr(), nullptr, capTable, elementCount, structSize, arena) : WireHelpers::initListPointer( result.tagAsPtr(), nullptr, capTable, elementCount, elementSize, arena); // Copy elements. switch (elementSize) { case ElementSize::INLINE_COMPOSITE: { ListElementCount pos = ZERO * ELEMENTS; for (auto& list: lists) { for (auto i: kj::zeroTo(list.size())) { builder.getStructElement(pos).copyContentFrom(list.getStructElement(i)); // assumeBits() safe because we checked total size earlier. pos = assumeBits(pos + ONE * ELEMENTS); } } break; } case ElementSize::POINTER: { ListElementCount pos = ZERO * ELEMENTS; for (auto& list: lists) { for (auto i: kj::zeroTo(list.size())) { builder.getPointerElement(pos).copyFrom(list.getPointerElement(i)); // assumeBits() safe because we checked total size earlier. pos = assumeBits(pos + ONE * ELEMENTS); } } break; } case ElementSize::BIT: { // It's difficult to memcpy() bits since a list could start or end mid-byte. For now we // do a slow, naive loop. Probably no one will ever care. ListElementCount pos = ZERO * ELEMENTS; for (auto& list: lists) { for (auto i: kj::zeroTo(list.size())) { builder.setDataElement(pos, list.getDataElement(i)); // assumeBits() safe because we checked total size earlier. pos = assumeBits(pos + ONE * ELEMENTS); } } break; } default: { // We know all the inputs are primitives with identical size because otherwise we would have // chosen INLINE_COMPOSITE. Therefore, we can safely use memcpy() here instead of copying // each element manually. byte* target = builder.ptr; auto step = builder.step / BITS_PER_BYTE; for (auto& list: lists) { auto count = step * upgradeBound(list.size()); WireHelpers::copyMemory(target, list.ptr, assumeBits(count)); target += count; } break; } } // Return orphan. result.segment = builder.segment; result.capTable = capTable; result.location = builder.getLocation(); return result; } OrphanBuilder OrphanBuilder::referenceExternalData(BuilderArena* arena, Data::Reader data) { KJ_REQUIRE(reinterpret_cast(data.begin()) % sizeof(void*) == 0, "Cannot referenceExternalData() that is not aligned."); auto checkedSize = assertMaxBits(bounded(data.size())); auto wordCount = WireHelpers::roundBytesUpToWords(checkedSize * BYTES); kj::ArrayPtr words(reinterpret_cast(data.begin()), unbound(wordCount / WORDS)); OrphanBuilder result; result.tagAsPtr()->setKindForOrphan(WirePointer::LIST); result.tagAsPtr()->listRef.set(ElementSize::BYTE, checkedSize * ELEMENTS); result.segment = arena->addExternalSegment(words); // External data cannot possibly contain capabilities. result.capTable = nullptr; // const_cast OK here because we will check whether the segment is writable when we try to get // a builder. result.location = const_cast(words.begin()); return result; } StructBuilder OrphanBuilder::asStruct(StructSize size) { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); StructBuilder result = WireHelpers::getWritableStructPointer( tagAsPtr(), location, segment, capTable, size, nullptr, segment->getArena()); // Watch out, the pointer could have been updated if the object had to be relocated. location = reinterpret_cast(result.data); return result; } ListBuilder OrphanBuilder::asList(ElementSize elementSize) { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); ListBuilder result = WireHelpers::getWritableListPointer( tagAsPtr(), location, segment, capTable, elementSize, nullptr, segment->getArena()); // Watch out, the pointer could have been updated if the object had to be relocated. // (Actually, currently this is not true for primitive lists, but let's not turn into a bug if // it changes!) location = result.getLocation(); return result; } ListBuilder OrphanBuilder::asStructList(StructSize elementSize) { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); ListBuilder result = WireHelpers::getWritableStructListPointer( tagAsPtr(), location, segment, capTable, elementSize, nullptr, segment->getArena()); // Watch out, the pointer could have been updated if the object had to be relocated. location = result.getLocation(); return result; } ListBuilder OrphanBuilder::asListAnySize() { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); ListBuilder result = WireHelpers::getWritableListPointerAnySize( tagAsPtr(), location, segment, capTable, nullptr, segment->getArena()); // Watch out, the pointer could have been updated if the object had to be relocated. location = result.getLocation(); return result; } Text::Builder OrphanBuilder::asText() { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); // Never relocates. return WireHelpers::getWritableTextPointer( tagAsPtr(), location, segment, capTable, nullptr, ZERO * BYTES); } Data::Builder OrphanBuilder::asData() { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); // Never relocates. return WireHelpers::getWritableDataPointer( tagAsPtr(), location, segment, capTable, nullptr, ZERO * BYTES); } StructReader OrphanBuilder::asStructReader(StructSize size) const { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); return WireHelpers::readStructPointer( segment, capTable, tagAsPtr(), location, nullptr, kj::maxValue); } ListReader OrphanBuilder::asListReader(ElementSize elementSize) const { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); return WireHelpers::readListPointer( segment, capTable, tagAsPtr(), location, nullptr, elementSize, kj::maxValue); } ListReader OrphanBuilder::asListReaderAnySize() const { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); return WireHelpers::readListPointer( segment, capTable, tagAsPtr(), location, nullptr, ElementSize::VOID /* dummy */, kj::maxValue); } #if !CAPNP_LITE kj::Own OrphanBuilder::asCapability() const { return WireHelpers::readCapabilityPointer(segment, capTable, tagAsPtr(), kj::maxValue); } #endif // !CAPNP_LITE Text::Reader OrphanBuilder::asTextReader() const { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); return WireHelpers::readTextPointer(segment, tagAsPtr(), location, nullptr, ZERO * BYTES); } Data::Reader OrphanBuilder::asDataReader() const { KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); return WireHelpers::readDataPointer(segment, tagAsPtr(), location, nullptr, ZERO * BYTES); } bool OrphanBuilder::truncate(ElementCount uncheckedSize, bool isText) { ListElementCount size = assertMaxBits(uncheckedSize, []() { KJ_FAIL_REQUIRE("requested list size is too large"); }); WirePointer* ref = tagAsPtr(); SegmentBuilder* segment = this->segment; word* target = WireHelpers::followFars(ref, location, segment); if (ref->isNull()) { // We don't know the right element size, so we can't resize this list. return size == ZERO * ELEMENTS; } KJ_REQUIRE(ref->kind() == WirePointer::LIST, "Schema mismatch: Can't truncate non-list.") { return false; } if (isText) { // Add space for the NUL terminator. size = assertMaxBits(size + ONE * ELEMENTS, []() { KJ_FAIL_REQUIRE("requested list size is too large"); }); } auto elementSize = ref->listRef.elementSize(); if (elementSize == ElementSize::INLINE_COMPOSITE) { auto oldWordCount = ref->listRef.inlineCompositeWordCount(); WirePointer* tag = reinterpret_cast(target); ++target; KJ_REQUIRE(tag->kind() == WirePointer::STRUCT, "INLINE_COMPOSITE lists of non-STRUCT type are not supported.") { return false; } StructSize structSize(tag->structRef.dataSize.get(), tag->structRef.ptrCount.get()); auto elementStep = structSize.total() / ELEMENTS; auto oldSize = tag->inlineCompositeListElementCount(); SegmentWordCount sizeWords = assertMaxBits( upgradeBound(size) * elementStep, []() { KJ_FAIL_ASSERT("requested list size too large to fit in message segment"); }); SegmentWordCount oldSizeWords = assertMaxBits( upgradeBound(oldSize) * elementStep, []() { KJ_FAIL_ASSERT("prior to truncate, list is larger than max segment size?"); }); word* newEndWord = target + sizeWords; word* oldEndWord = target + oldWordCount; if (size <= oldSize) { // Zero the trailing elements. for (auto i: kj::range(size, oldSize)) { // assumeBits() safe because we checked that both sizeWords and oldSizeWords are in-range // above. WireHelpers::zeroObject(segment, capTable, tag, target + assumeBits(upgradeBound(i) * elementStep)); } ref->listRef.setInlineComposite(sizeWords); tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, size); segment->tryTruncate(oldEndWord, newEndWord); } else if (newEndWord <= oldEndWord) { // Apparently the old list was over-allocated? The word count is more than needed to store // the elements. This is "valid" but shouldn't happen in practice unless someone is toying // with us. word* expectedEnd = target + oldSizeWords; KJ_ASSERT(newEndWord >= expectedEnd); WireHelpers::zeroMemory(expectedEnd, intervalLength(expectedEnd, newEndWord, MAX_SEGMENT_WORDS)); tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, size); } else { if (segment->tryExtend(oldEndWord, newEndWord)) { // Done in-place. Nothing else to do now; the new memory is already zero'd. ref->listRef.setInlineComposite(sizeWords); tag->setKindAndInlineCompositeListElementCount(WirePointer::STRUCT, size); } else { // Need to re-allocate and transfer. OrphanBuilder replacement = initStructList(segment->getArena(), capTable, size, structSize); ListBuilder newList = replacement.asStructList(structSize); for (auto i: kj::zeroTo(oldSize)) { // assumeBits() safe because we checked that both sizeWords and oldSizeWords are in-range // above. word* element = target + assumeBits(upgradeBound(i) * elementStep); newList.getStructElement(i).transferContentFrom( StructBuilder(segment, capTable, element, reinterpret_cast(element + structSize.data), structSize.data * BITS_PER_WORD, structSize.pointers)); } *this = kj::mv(replacement); } } } else if (elementSize == ElementSize::POINTER) { // TODO(cleanup): GCC won't let me declare this constexpr, claiming POINTERS is not constexpr, // but it is? const auto POINTERS_PER_ELEMENT = ONE * POINTERS / ELEMENTS; auto oldSize = ref->listRef.elementCount(); word* newEndWord = target + size * POINTERS_PER_ELEMENT * WORDS_PER_POINTER; word* oldEndWord = target + oldSize * POINTERS_PER_ELEMENT * WORDS_PER_POINTER; if (size <= oldSize) { // Zero the trailing elements. for (WirePointer* element = reinterpret_cast(newEndWord); element < reinterpret_cast(oldEndWord); ++element) { WireHelpers::zeroPointerAndFars(segment, element); } ref->listRef.set(ElementSize::POINTER, size); segment->tryTruncate(oldEndWord, newEndWord); } else { if (segment->tryExtend(oldEndWord, newEndWord)) { // Done in-place. Nothing else to do now; the new memory is already zero'd. ref->listRef.set(ElementSize::POINTER, size); } else { // Need to re-allocate and transfer. OrphanBuilder replacement = initList( segment->getArena(), capTable, size, ElementSize::POINTER); ListBuilder newList = replacement.asList(ElementSize::POINTER); WirePointer* oldPointers = reinterpret_cast(target); for (auto i: kj::zeroTo(oldSize)) { newList.getPointerElement(i).transferFrom( PointerBuilder(segment, capTable, oldPointers + i * POINTERS_PER_ELEMENT)); } *this = kj::mv(replacement); } } } else { auto oldSize = ref->listRef.elementCount(); auto step = dataBitsPerElement(elementSize); const auto MAX_STEP_BYTES = ONE * WORDS / ELEMENTS * BYTES_PER_WORD; word* newEndWord = target + WireHelpers::roundBitsUpToWords( upgradeBound(size) * step); word* oldEndWord = target + WireHelpers::roundBitsUpToWords( upgradeBound(oldSize) * step); if (size <= oldSize) { // When truncating text, we want to set the null terminator as well, so we'll do our zeroing // at the byte level. byte* begin = reinterpret_cast(target); byte* newEndByte = begin + WireHelpers::roundBitsUpToBytes( upgradeBound(size) * step) - isText; byte* oldEndByte = reinterpret_cast(oldEndWord); WireHelpers::zeroMemory(newEndByte, intervalLength(newEndByte, oldEndByte, MAX_LIST_ELEMENTS * MAX_STEP_BYTES)); ref->listRef.set(elementSize, size); segment->tryTruncate(oldEndWord, newEndWord); } else { // We're trying to extend, not truncate. if (segment->tryExtend(oldEndWord, newEndWord)) { // Done in-place. Nothing else to do now; the memory is already zero'd. ref->listRef.set(elementSize, size); } else { // Need to re-allocate and transfer. OrphanBuilder replacement = initList(segment->getArena(), capTable, size, elementSize); ListBuilder newList = replacement.asList(elementSize); auto words = WireHelpers::roundBitsUpToWords( dataBitsPerElement(elementSize) * upgradeBound(oldSize)); WireHelpers::copyMemory(reinterpret_cast(newList.ptr), target, words); *this = kj::mv(replacement); } } } return true; } void OrphanBuilder::truncate(ElementCount size, ElementSize elementSize) { if (!truncate(size, false)) { // assumeBits() safe since it's checked inside truncate() *this = initList(segment->getArena(), capTable, assumeBits(size), elementSize); } } void OrphanBuilder::truncate(ElementCount size, StructSize elementSize) { if (!truncate(size, false)) { // assumeBits() safe since it's checked inside truncate() *this = initStructList(segment->getArena(), capTable, assumeBits(size), elementSize); } } void OrphanBuilder::truncateText(ElementCount size) { if (!truncate(size, true)) { // assumeBits() safe since it's checked inside truncate() *this = initText(segment->getArena(), capTable, assumeBits(size) * (ONE * BYTES / ELEMENTS)); } } void OrphanBuilder::euthanize() { // Carefully catch any exceptions and rethrow them as recoverable exceptions since we may be in // a destructor. auto exception = kj::runCatchingExceptions([&]() { if (tagAsPtr()->isPositional()) { WireHelpers::zeroObject(segment, capTable, tagAsPtr(), location); } else { WireHelpers::zeroObject(segment, capTable, tagAsPtr()); } WireHelpers::zeroMemory(&tag, ONE * WORDS); segment = nullptr; location = nullptr; }); KJ_IF_MAYBE(e, exception) { kj::getExceptionCallback().onRecoverableException(kj::mv(*e)); } } } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/capability.c++0000644000175000017500000012530214712011043021241 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "capability.h" #include "message.h" #include "arena.h" #include #include #include #include #include "generated-header-support.h" namespace capnp { namespace _ { void setGlobalBrokenCapFactoryForLayoutCpp(BrokenCapFactory& factory); // Defined in layout.c++. } // namespace _ namespace { static kj::Own newNullCap(); class BrokenCapFactoryImpl: public _::BrokenCapFactory { public: kj::Own newBrokenCap(kj::StringPtr description) override { return capnp::newBrokenCap(description); } kj::Own newNullCap() override { return capnp::newNullCap(); } }; static BrokenCapFactoryImpl brokenCapFactory; } // namespace ClientHook::ClientHook() { setGlobalBrokenCapFactoryForLayoutCpp(brokenCapFactory); } // ======================================================================================= Capability::Client::Client(decltype(nullptr)) : hook(newNullCap()) {} Capability::Client::Client(kj::Exception&& exception) : hook(newBrokenCap(kj::mv(exception))) {} kj::Promise> Capability::Client::getFd() { auto fd = hook->getFd(); if (fd != nullptr) { return fd; } else KJ_IF_MAYBE(promise, hook->whenMoreResolved()) { return promise->attach(hook->addRef()).then([](kj::Own newHook) { return Client(kj::mv(newHook)).getFd(); }); } else { return kj::Maybe(nullptr); } } kj::Maybe> Capability::Server::shortenPath() { return nullptr; } Capability::Server::DispatchCallResult Capability::Server::internalUnimplemented( const char* actualInterfaceName, uint64_t requestedTypeId) { return { KJ_EXCEPTION(UNIMPLEMENTED, "Requested interface not implemented.", actualInterfaceName, requestedTypeId), false, true }; } Capability::Server::DispatchCallResult Capability::Server::internalUnimplemented( const char* interfaceName, uint64_t typeId, uint16_t methodId) { return { KJ_EXCEPTION(UNIMPLEMENTED, "Method not implemented.", interfaceName, typeId, methodId), false, true }; } kj::Promise Capability::Server::internalUnimplemented( const char* interfaceName, const char* methodName, uint64_t typeId, uint16_t methodId) { return KJ_EXCEPTION(UNIMPLEMENTED, "Method not implemented.", interfaceName, typeId, methodName, methodId); } ResponseHook::~ResponseHook() noexcept(false) {} kj::Promise ClientHook::whenResolved() { KJ_IF_MAYBE(promise, whenMoreResolved()) { return promise->then([](kj::Own&& resolution) { return resolution->whenResolved(); }); } else { return kj::READY_NOW; } } kj::Promise Capability::Client::whenResolved() { return hook->whenResolved().attach(hook->addRef()); } // ======================================================================================= static inline uint firstSegmentSize(kj::Maybe sizeHint) { KJ_IF_MAYBE(s, sizeHint) { return s->wordCount; } else { return SUGGESTED_FIRST_SEGMENT_WORDS; } } class LocalResponse final: public ResponseHook { public: LocalResponse(kj::Maybe sizeHint) : message(firstSegmentSize(sizeHint)) {} MallocMessageBuilder message; }; class LocalCallContext final: public CallContextHook, public ResponseHook, public kj::Refcounted { public: LocalCallContext(kj::Own&& request, kj::Own clientRef, ClientHook::CallHints hints, bool isStreaming) : request(kj::mv(request)), clientRef(kj::mv(clientRef)), hints(hints), isStreaming(isStreaming) {} AnyPointer::Reader getParams() override { KJ_IF_MAYBE(r, request) { return r->get()->getRoot(); } else { KJ_FAIL_REQUIRE("Can't call getParams() after releaseParams()."); } } void releaseParams() override { request = nullptr; } AnyPointer::Builder getResults(kj::Maybe sizeHint) override { if (response == nullptr) { auto localResponse = kj::heap(sizeHint); responseBuilder = localResponse->message.getRoot(); response = Response(responseBuilder.asReader(), kj::mv(localResponse)); } return responseBuilder; } void setPipeline(kj::Own&& pipeline) override { KJ_IF_MAYBE(f, tailCallPipelineFulfiller) { f->get()->fulfill(AnyPointer::Pipeline(kj::mv(pipeline))); } } kj::Promise tailCall(kj::Own&& request) override { auto result = directTailCall(kj::mv(request)); KJ_IF_MAYBE(f, tailCallPipelineFulfiller) { f->get()->fulfill(AnyPointer::Pipeline(kj::mv(result.pipeline))); } return kj::mv(result.promise); } ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own&& request) override { KJ_REQUIRE(response == nullptr, "Can't call tailCall() after initializing the results struct."); if (hints.onlyPromisePipeline) { return { kj::NEVER_DONE, PipelineHook::from(request->sendForPipeline()) }; } if (isStreaming) { auto promise = request->sendStreaming(); return { kj::mv(promise), getDisabledPipeline() }; } else { auto promise = request->send(); auto voidPromise = promise.then([this](Response&& tailResponse) { response = kj::mv(tailResponse); }); return { kj::mv(voidPromise), PipelineHook::from(kj::mv(promise)) }; } } kj::Promise onTailCall() override { auto paf = kj::newPromiseAndFulfiller(); tailCallPipelineFulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } kj::Own addRef() override { return kj::addRef(*this); } kj::Maybe> request; kj::Maybe> response; AnyPointer::Builder responseBuilder = nullptr; // only valid if `response` is non-null kj::Own clientRef; kj::Maybe>> tailCallPipelineFulfiller; ClientHook::CallHints hints; bool isStreaming; }; class LocalRequest final: public RequestHook { public: inline LocalRequest(uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, ClientHook::CallHints hints, kj::Own client) : message(kj::heap(firstSegmentSize(sizeHint))), interfaceId(interfaceId), methodId(methodId), hints(hints), client(kj::mv(client)) {} RemotePromise send() override { bool isStreaming = false; return sendImpl(isStreaming); } kj::Promise sendStreaming() override { // We don't do any special handling of streaming in RequestHook for local requests, because // there is no latency to compensate for between the client and server in this case. However, // we record whether the call was streaming, so that it can be preserved as a streaming call // if the local capability later resolves to a remote capability. bool isStreaming = true; return sendImpl(isStreaming).ignoreResult(); } AnyPointer::Pipeline sendForPipeline() override { KJ_REQUIRE(message.get() != nullptr, "Already called send() on this request."); hints.onlyPromisePipeline = true; bool isStreaming = false; auto context = kj::refcounted( kj::mv(message), client->addRef(), hints, isStreaming); auto vpap = client->call(interfaceId, methodId, kj::addRef(*context), hints); return AnyPointer::Pipeline(kj::mv(vpap.pipeline)); } const void* getBrand() override { return nullptr; } kj::Own message; private: uint64_t interfaceId; uint16_t methodId; ClientHook::CallHints hints; kj::Own client; RemotePromise sendImpl(bool isStreaming) { KJ_REQUIRE(message.get() != nullptr, "Already called send() on this request."); auto context = kj::refcounted(kj::mv(message), client->addRef(), hints, isStreaming); auto promiseAndPipeline = client->call(interfaceId, methodId, kj::addRef(*context), hints); // Now the other branch returns the response from the context. auto promise = promiseAndPipeline.promise.then([context=kj::mv(context)]() mutable { // force response allocation auto reader = context->getResults(MessageSize { 0, 0 }).asReader(); if (context->isShared()) { // We can't just move away context->response as `context` itself is still referenced by // something -- probably a Pipeline object. As a bit of a hack, LocalCallContext itself // implements ResponseHook so that we can just return a ref on it. // // TODO(cleanup): Maybe ResponseHook should be refcounted? Note that context->response // might not necessarily contain a LocalResponse if it was resolved by a tail call, so // we'd have to add refcounting to all ResponseHook implementations. context->releaseParams(); // The call is done so params can definitely be dropped. context->clientRef = nullptr; // Definitely not using the client cap anymore either. return Response(reader, kj::mv(context)); } else { return kj::mv(KJ_ASSERT_NONNULL(context->response)); } }); // We return the other branch. return RemotePromise( kj::mv(promise), AnyPointer::Pipeline(kj::mv(promiseAndPipeline.pipeline))); } }; // ======================================================================================= // Call queues // // These classes handle pipelining in the case where calls need to be queued in-memory until some // local operation completes. class QueuedPipeline final: public PipelineHook, public kj::Refcounted { // A PipelineHook which simply queues calls while waiting for a PipelineHook to which to forward // them. public: QueuedPipeline(kj::Promise>&& promiseParam) : promise(promiseParam.fork()), selfResolutionOp(promise.addBranch().then([this](kj::Own&& inner) { redirect = kj::mv(inner); }, [this](kj::Exception&& exception) { redirect = newBrokenPipeline(kj::mv(exception)); }).eagerlyEvaluate(nullptr)) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { auto copy = kj::heapArrayBuilder(ops.size()); for (auto& op: ops) { copy.add(op); } return getPipelinedCap(copy.finish()); } kj::Own getPipelinedCap(kj::Array&& ops) override; private: kj::ForkedPromise> promise; kj::Maybe> redirect; // Once the promise resolves, this will become non-null and point to the underlying object. kj::Promise selfResolutionOp; // Represents the operation which will set `redirect` when possible. kj::HashMap, kj::Own> clientMap; // If the same pipelined cap is requested twice, we have to return the same object. This is // necessary because each ClientHook we create is a QueuedClient which queues up calls. If we // return a new one each time, there will be several queues, and ordering of calls will be lost // between the queues. // // One case where this is particularly problematic is with promises resolved over RPC. Consider // this case: // // * Alice holds a promise capability P pointing towards Bob. // * Bob makes a call Q on an object hosted by Alice. // * Without waiting for Q to complete, Bob obtains a pipelined-promise capability for Q's // eventual result, P2. // * Alice invokes a method M on P. The call is sent to Bob. // * Bob resolves Alice's original promise P to P2. // * Alice receives a Resolve message from Bob resolving P to Q's eventual result. // * As a result, Alice calls getPipelinedCap() on the QueuedPipeline for Q's result, which // returns a QueuedClient for that result, which we'll call QR1. // * Alice also sends a Disembargo to Bob. // * Alice calls a method M2 on P. This call is blocked locally waiting for the disembargo to // complete. // * Bob receives Alice's first method call, M. Since it's addressed to P, which later resolved // to Q's result, Bob reflects the call back to Alice. // * Alice receives the reflected call, which is addressed to Q's result. // * Alice calls getPipelinedCap() on the QueuedPipeline for Q's result, which returns a // QueuedClient for that result, which we'll call QR2. // * Alice enqueues the call M on QR2. // * Bob receives Alice's Disembargo message, and reflects it back. // * Alices receives the Disembrago. // * Alice unblocks the method cgall M2, which had been blocked on the embargo. // * The call M2 is then equeued onto QR1. // * Finally, the call Q completes. // * This causes QR1 and QR2 to resolve to their final destinations. But if QR1 and QR2 are // separate objects, then one of them must resolve first. QR1 was created first, so naturally // it resolves first, followed by QR2. // * Because QR1 resolves first, method call M2 is delivered first. // * QR2 resolves second, so method call M1 is delivered next. // * THIS IS THE WRONG ORDER! // // In order to avoid this problem, it's necessary for QR1 and QR2 to be the same object, so that // they share the same call queue. In this case, M2 is correctly enqueued onto QR2 *after* M1 was // enqueued on QR1, and so the method calls are delivered in the correct order. }; class QueuedClient final: public ClientHook, public kj::Refcounted { // A ClientHook which simply queues calls while waiting for a ClientHook to which to forward // them. public: QueuedClient(kj::Promise>&& promiseParam) : promise(promiseParam.fork()), selfResolutionOp(promise.addBranch().then([this](kj::Own&& inner) { redirect = kj::mv(inner); }, [this](kj::Exception&& exception) { redirect = newBrokenCap(kj::mv(exception)); }).eagerlyEvaluate(nullptr)), promiseForCallForwarding(promise.addBranch().fork()), promiseForClientResolution(promise.addBranch().fork()) {} Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { auto hook = kj::heap( interfaceId, methodId, sizeHint, hints, kj::addRef(*this)); auto root = hook->message->getRoot(); return Request(root, kj::mv(hook)); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { if (hints.noPromisePipelining) { // Optimize for no pipelining. auto promise = promiseForCallForwarding.addBranch() .then([=,context=kj::mv(context)](kj::Own&& client) mutable { return client->call(interfaceId, methodId, kj::mv(context), hints).promise; }); return VoidPromiseAndPipeline { kj::mv(promise), getDisabledPipeline() }; } else if (hints.onlyPromisePipeline) { auto pipelinePromise = promiseForCallForwarding.addBranch() .then([=,context=kj::mv(context)](kj::Own&& client) mutable { return client->call(interfaceId, methodId, kj::mv(context), hints).pipeline; }); return VoidPromiseAndPipeline { kj::NEVER_DONE, kj::refcounted(kj::mv(pipelinePromise)) }; } else { auto split = promiseForCallForwarding.addBranch() .then([=,context=kj::mv(context)](kj::Own&& client) mutable { auto vpap = client->call(interfaceId, methodId, kj::mv(context), hints); return kj::tuple(kj::mv(vpap.promise), kj::mv(vpap.pipeline)); }).split(); kj::Promise completionPromise = kj::mv(kj::get<0>(split)); kj::Promise> pipelinePromise = kj::mv(kj::get<1>(split)); auto pipeline = kj::refcounted(kj::mv(pipelinePromise)); // OK, now we can actually return our thing. return VoidPromiseAndPipeline { kj::mv(completionPromise), kj::mv(pipeline) }; } } kj::Maybe getResolved() override { KJ_IF_MAYBE(inner, redirect) { return **inner; } else { return nullptr; } } kj::Maybe>> whenMoreResolved() override { return promiseForClientResolution.addBranch(); } kj::Own addRef() override { return kj::addRef(*this); } const void* getBrand() override { return nullptr; } kj::Maybe getFd() override { KJ_IF_MAYBE(r, redirect) { return r->get()->getFd(); } else { return nullptr; } } private: typedef kj::ForkedPromise> ClientHookPromiseFork; kj::Maybe> redirect; // Once the promise resolves, this will become non-null and point to the underlying object. ClientHookPromiseFork promise; // Promise that resolves when we have a new ClientHook to forward to. // // This fork shall only have three branches: `selfResolutionOp`, `promiseForCallForwarding`, and // `promiseForClientResolution`, in that order. kj::Promise selfResolutionOp; // Represents the operation which will set `redirect` when possible. ClientHookPromiseFork promiseForCallForwarding; // When this promise resolves, each queued call will be forwarded to the real client. This needs // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure // previously-queued calls are delivered before any new calls made in response to the resolution. ClientHookPromiseFork promiseForClientResolution; // whenMoreResolved() returns forks of this promise. These must resolve *after* queued calls // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly // delivered after calls made earlier), but *before* any queued calls return (because it might // confuse the application if a queued call returns before the capability on which it was made // resolves). Luckily, we know that queued calls will involve, at the very least, an // eventLoop.evalLater. }; kj::Own QueuedPipeline::getPipelinedCap(kj::Array&& ops) { KJ_IF_MAYBE(r, redirect) { return r->get()->getPipelinedCap(kj::mv(ops)); } else { return clientMap.findOrCreate(ops.asPtr(), [&]() { auto clientPromise = promise.addBranch() .then([ops = KJ_MAP(op, ops) { return op; }](kj::Own pipeline) { return pipeline->getPipelinedCap(kj::mv(ops)); }); return kj::HashMap, kj::Own>::Entry { kj::mv(ops), kj::refcounted(kj::mv(clientPromise)) }; })->addRef(); } } // ======================================================================================= class LocalPipeline final: public PipelineHook, public kj::Refcounted { public: inline LocalPipeline(kj::Own&& contextParam) : context(kj::mv(contextParam)), results(context->getResults(MessageSize { 0, 0 })) {} kj::Own addRef() { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) { return results.getPipelinedCap(ops); } private: kj::Own context; AnyPointer::Reader results; }; class LocalClient final: public ClientHook, public kj::Refcounted { public: LocalClient(kj::Own&& serverParam, bool revocable = false) { auto& serverRef = *server.emplace(kj::mv(serverParam)); serverRef.thisHook = this; if (revocable) revoker.emplace(); startResolveTask(serverRef); } LocalClient(kj::Own&& serverParam, _::CapabilityServerSetBase& capServerSet, void* ptr, bool revocable = false) : capServerSet(&capServerSet), ptr(ptr) { auto& serverRef = *server.emplace(kj::mv(serverParam)); serverRef.thisHook = this; if (revocable) revoker.emplace(); startResolveTask(serverRef); } ~LocalClient() noexcept(false) { KJ_IF_MAYBE(s, server) { s->get()->thisHook = nullptr; } } void revoke(kj::Exception&& e) { KJ_IF_MAYBE(s, server) { KJ_ASSERT_NONNULL(revoker).cancel(e); brokenException = kj::mv(e); s->get()->thisHook = nullptr; server = nullptr; } } Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { KJ_IF_MAYBE(r, resolved) { // We resolved to a shortened path. New calls MUST go directly to the replacement capability // so that their ordering is consistent with callers who call getResolved() to get direct // access to the new capability. In particular it's important that we don't place these calls // in our streaming queue. return r->get()->newCall(interfaceId, methodId, sizeHint, hints); } auto hook = kj::heap( interfaceId, methodId, sizeHint, hints, kj::addRef(*this)); auto root = hook->message->getRoot(); return Request(root, kj::mv(hook)); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { KJ_IF_MAYBE(r, resolved) { // We resolved to a shortened path. New calls MUST go directly to the replacement capability // so that their ordering is consistent with callers who call getResolved() to get direct // access to the new capability. In particular it's important that we don't place these calls // in our streaming queue. return r->get()->call(interfaceId, methodId, kj::mv(context), hints); } auto contextPtr = context.get(); // We don't want to actually dispatch the call synchronously, because we don't want the callee // to have any side effects before the promise is returned to the caller. This helps avoid // race conditions. // // So, we do an evalLater() here. // // Note also that QueuedClient depends on this evalLater() to ensure that pipelined calls don't // complete before 'whenMoreResolved()' promises resolve. auto promise = kj::evalLater([this,interfaceId,methodId,contextPtr]() { if (blocked) { return kj::newAdaptedPromise, BlockedCall>( *this, interfaceId, methodId, *contextPtr); } else { return callInternal(interfaceId, methodId, *contextPtr); } }).attach(kj::addRef(*this)); if (hints.noPromisePipelining) { // No need to set up pipelining.. // Make sure we release the params on return, since we would on the normal pipelining path. // TODO(perf): Experiment with whether this is actually useful. It seems likely the params // will be released soon anyway, so maybe this is a waste? promise = promise.then([context=kj::mv(context)]() mutable { context->releaseParams(); }); // When we do apply pipelining, the use of `.fork()` has the side effect of eagerly // evaluating the promise. To match the behavior here, we use `.eagerlyEvaluate()`. // TODO(perf): Maybe we don't need to match behavior? It did break some tests but arguably // those tests are weird and not what a real program would do... promise = promise.eagerlyEvaluate(nullptr); return VoidPromiseAndPipeline { kj::mv(promise), getDisabledPipeline() }; } kj::Promise completionPromise = nullptr; kj::Promise pipelineBranch = nullptr; if (hints.onlyPromisePipeline) { pipelineBranch = kj::mv(promise); completionPromise = kj::NEVER_DONE; } else { // We have to fork this promise for the pipeline to receive a copy of the answer. auto forked = promise.fork(); pipelineBranch = forked.addBranch(); completionPromise = forked.addBranch().attach(context->addRef()); } auto pipelinePromise = pipelineBranch .then([=,context=context->addRef()]() mutable -> kj::Own { context->releaseParams(); return kj::refcounted(kj::mv(context)); }); auto tailPipelinePromise = context->onTailCall() .then([context = context->addRef()](AnyPointer::Pipeline&& pipeline) { return kj::mv(pipeline.hook); }); pipelinePromise = pipelinePromise.exclusiveJoin(kj::mv(tailPipelinePromise)); return VoidPromiseAndPipeline { kj::mv(completionPromise), kj::refcounted(kj::mv(pipelinePromise)) }; } kj::Maybe getResolved() override { return resolved.map([](kj::Own& hook) -> ClientHook& { return *hook; }); } kj::Maybe>> whenMoreResolved() override { KJ_IF_MAYBE(r, resolved) { return kj::Promise>(r->get()->addRef()); } else KJ_IF_MAYBE(t, resolveTask) { return t->addBranch().then([this]() { return KJ_ASSERT_NONNULL(resolved)->addRef(); }); } else { return nullptr; } } kj::Own addRef() override { return kj::addRef(*this); } static const uint BRAND; // Value is irrelevant; used for pointer. const void* getBrand() override { return &BRAND; } kj::Maybe> getLocalServer(_::CapabilityServerSetBase& capServerSet) { // If this is a local capability created through `capServerSet`, return the underlying Server. // Otherwise, return nullptr. Default implementation (which everyone except LocalClient should // use) always returns nullptr. if (this->capServerSet == &capServerSet) { if (blocked) { // If streaming calls are in-flight, it could be the case that they were originally sent // over RPC and reflected back, before the capability had resolved to a local object. In // that case, the client may already perceive these calls as "done" because the RPC // implementation caused the client promise to resolve early. However, the capability is // now local, and the app is trying to break through the LocalClient wrapper and access // the server directly, bypassing the stream queue. Since the app thinks that all // previous calls already completed, it may then try to queue a new call directly on the // server, jumping the queue. // // We can solve this by delaying getLocalServer() until all current streaming calls have // finished. Note that if a new streaming call is started *after* this point, we need not // worry about that, because in this case it is presumably a local call and the caller // won't be informed of completion until the call actually does complete. Thus the caller // is well-aware that this call is still in-flight. // // However, the app still cannot assume that there aren't multiple clients, perhaps even // a malicious client that tries to send stream requests that overlap with the app's // direct use of the server... so it's up to the app to check for and guard against // concurrent calls after using getLocalServer(). return kj::newAdaptedPromise, BlockedCall>(*this) .then([this]() { return ptr; }); } else { return kj::Promise(ptr); } } else { return nullptr; } } kj::Maybe getFd() override { KJ_IF_MAYBE(s, server) { return s->get()->getFd(); } else { return nullptr; } } private: kj::Maybe> server; _::CapabilityServerSetBase* capServerSet = nullptr; void* ptr = nullptr; kj::Maybe> resolveTask; kj::Maybe> resolved; kj::Maybe revoker; // If non-null, all promises must be wrapped in this revoker. void startResolveTask(Capability::Server& serverRef) { resolveTask = serverRef.shortenPath().map([this](kj::Promise promise) { KJ_IF_MAYBE(r, revoker) { promise = r->wrap(kj::mv(promise)); } return promise.then([this](Capability::Client&& cap) { auto hook = ClientHook::from(kj::mv(cap)); if (blocked) { // This is a streaming interface and we have some calls queued up as a result. We cannot // resolve directly to the new shorter path because this may allow new calls to hop // the queue -- we need to embargo new calls until the queue clears out. auto promise = kj::newAdaptedPromise, BlockedCall>(*this) .then([hook = kj::mv(hook)]() mutable { return kj::mv(hook); }); hook = newLocalPromiseClient(kj::mv(promise)); } resolved = kj::mv(hook); }).fork(); }); } class BlockedCall { public: BlockedCall(kj::PromiseFulfiller>& fulfiller, LocalClient& client, uint64_t interfaceId, uint16_t methodId, CallContextHook& context) : fulfiller(fulfiller), client(client), interfaceId(interfaceId), methodId(methodId), context(context), prev(client.blockedCallsEnd) { *prev = *this; client.blockedCallsEnd = &next; } BlockedCall(kj::PromiseFulfiller>& fulfiller, LocalClient& client) : fulfiller(fulfiller), client(client), prev(client.blockedCallsEnd) { *prev = *this; client.blockedCallsEnd = &next; } ~BlockedCall() noexcept(false) { unlink(); } void unblock() { unlink(); KJ_IF_MAYBE(c, context) { fulfiller.fulfill(kj::evalNow([&]() { return client.callInternal(interfaceId, methodId, *c); })); } else { // This is just a barrier. fulfiller.fulfill(kj::READY_NOW); } } private: kj::PromiseFulfiller>& fulfiller; LocalClient& client; uint64_t interfaceId; uint16_t methodId; kj::Maybe context; kj::Maybe next; kj::Maybe* prev; void unlink() { if (prev != nullptr) { *prev = next; KJ_IF_MAYBE(n, next) { n->prev = prev; } else { client.blockedCallsEnd = prev; } prev = nullptr; } } }; class BlockingScope { public: BlockingScope(LocalClient& client): client(client) { client.blocked = true; } BlockingScope(): client(nullptr) {} BlockingScope(BlockingScope&& other): client(other.client) { other.client = nullptr; } KJ_DISALLOW_COPY(BlockingScope); ~BlockingScope() noexcept(false) { KJ_IF_MAYBE(c, client) { c->unblock(); } } private: kj::Maybe client; }; bool blocked = false; kj::Maybe brokenException; kj::Maybe blockedCalls; kj::Maybe* blockedCallsEnd = &blockedCalls; void unblock() { blocked = false; while (!blocked) { KJ_IF_MAYBE(t, blockedCalls) { t->unblock(); } else { break; } } } kj::Promise callInternal(uint64_t interfaceId, uint16_t methodId, CallContextHook& context) { KJ_ASSERT(!blocked); KJ_IF_MAYBE(e, brokenException) { // Previous streaming call threw, so everything fails from now on. return kj::cp(*e); } // `server` can't be null here since `brokenException` is null. auto result = KJ_ASSERT_NONNULL(server)->dispatchCall(interfaceId, methodId, CallContext(context)); KJ_IF_MAYBE(r, revoker) { result.promise = r->wrap(kj::mv(result.promise)); } if (!result.allowCancellation) { // Make sure this call cannot be canceled by forking the promise and detaching one branch. auto fork = result.promise.attach(kj::addRef(*this), context.addRef()).fork(); result.promise = fork.addBranch(); fork.addBranch().detach([](kj::Exception&&) { // Exception from canceled call is silently discarded. The caller should have waited for // it if they cared. }); } if (result.isStreaming) { return result.promise .catch_([this](kj::Exception&& e) { brokenException = kj::cp(e); kj::throwRecoverableException(kj::mv(e)); }).attach(BlockingScope(*this)); } else { return kj::mv(result.promise); } } }; const uint LocalClient::BRAND = 0; kj::Own Capability::Client::makeLocalClient(kj::Own&& server) { return kj::refcounted(kj::mv(server)); } kj::Own Capability::Client::makeRevocableLocalClient(Capability::Server& server) { auto result = kj::refcounted( kj::Own(&server, kj::NullDisposer::instance), true /* revocable */); return result; } void Capability::Client::revokeLocalClient(ClientHook& hook) { revokeLocalClient(hook, KJ_EXCEPTION(FAILED, "capability was revoked (RevocableServer was destroyed)")); } void Capability::Client::revokeLocalClient(ClientHook& hook, kj::Exception&& e) { kj::downcast(hook).revoke(kj::mv(e)); } kj::Own newLocalPromiseClient(kj::Promise>&& promise) { return kj::refcounted(kj::mv(promise)); } kj::Own newLocalPromisePipeline(kj::Promise>&& promise) { return kj::refcounted(kj::mv(promise)); } // ======================================================================================= namespace _ { // private class PipelineBuilderHook final: public PipelineHook, public kj::Refcounted { public: PipelineBuilderHook(uint firstSegmentWords) : message(firstSegmentWords), root(message.getRoot()) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { return root.asReader().getPipelinedCap(ops); } MallocMessageBuilder message; AnyPointer::Builder root; }; PipelineBuilderPair newPipelineBuilder(uint firstSegmentWords) { auto hook = kj::refcounted(firstSegmentWords); auto root = hook->root; return { root, kj::mv(hook) }; } } // namespace _ (private) // ======================================================================================= namespace { class BrokenPipeline final: public PipelineHook, public kj::Refcounted { public: BrokenPipeline(const kj::Exception& exception): exception(exception) {} kj::Own addRef() override { return kj::addRef(*this); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override; private: kj::Exception exception; }; class BrokenRequest final: public RequestHook { public: BrokenRequest(const kj::Exception& exception, kj::Maybe sizeHint) : exception(exception), message(firstSegmentSize(sizeHint)) {} RemotePromise send() override { return RemotePromise(kj::cp(exception), AnyPointer::Pipeline(kj::refcounted(exception))); } kj::Promise sendStreaming() override { return kj::cp(exception); } AnyPointer::Pipeline sendForPipeline() override { return AnyPointer::Pipeline(kj::refcounted(exception)); } const void* getBrand() override { return nullptr; } kj::Exception exception; MallocMessageBuilder message; }; class BrokenClient final: public ClientHook, public kj::Refcounted { public: BrokenClient(const kj::Exception& exception, bool resolved, const void* brand) : exception(exception), resolved(resolved), brand(brand) {} BrokenClient(const kj::StringPtr description, bool resolved, const void* brand) : exception(kj::Exception::Type::FAILED, "", 0, kj::str(description)), resolved(resolved), brand(brand) {} Request newCall( uint64_t interfaceId, uint16_t methodId, kj::Maybe sizeHint, CallHints hints) override { return newBrokenRequest(kj::cp(exception), sizeHint); } VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, kj::Own&& context, CallHints hints) override { return VoidPromiseAndPipeline { kj::cp(exception), kj::refcounted(exception) }; } kj::Maybe getResolved() override { return nullptr; } kj::Maybe>> whenMoreResolved() override { if (resolved) { return nullptr; } else { return kj::Promise>(kj::cp(exception)); } } kj::Own addRef() override { return kj::addRef(*this); } const void* getBrand() override { return brand; } kj::Maybe getFd() override { return nullptr; } private: kj::Exception exception; bool resolved; const void* brand; }; kj::Own BrokenPipeline::getPipelinedCap(kj::ArrayPtr ops) { return kj::refcounted(exception, false, &ClientHook::BROKEN_CAPABILITY_BRAND); } kj::Own newNullCap() { // A null capability, unlike other broken capabilities, is considered resolved. return kj::refcounted("Called null capability.", true, &ClientHook::NULL_CAPABILITY_BRAND); } } // namespace kj::Own newBrokenCap(kj::StringPtr reason) { return kj::refcounted(reason, false, &ClientHook::BROKEN_CAPABILITY_BRAND); } kj::Own newBrokenCap(kj::Exception&& reason) { return kj::refcounted(kj::mv(reason), false, &ClientHook::BROKEN_CAPABILITY_BRAND); } kj::Own newBrokenPipeline(kj::Exception&& reason) { return kj::refcounted(kj::mv(reason)); } Request newBrokenRequest( kj::Exception&& reason, kj::Maybe sizeHint) { auto hook = kj::heap(kj::mv(reason), sizeHint); auto root = hook->message.getRoot(); return Request(root, kj::mv(hook)); } kj::Own getDisabledPipeline() { class DisabledPipelineHook final: public PipelineHook { public: kj::Own addRef() override { return kj::Own(this, kj::NullDisposer::instance); } kj::Own getPipelinedCap(kj::ArrayPtr ops) override { return newBrokenCap(KJ_EXCEPTION(FAILED, "caller specified noPromisePipelining hint, but then tried to pipeline")); } kj::Own getPipelinedCap(kj::Array&& ops) override { return newBrokenCap(KJ_EXCEPTION(FAILED, "caller specified noPromisePipelining hint, but then tried to pipeline")); } }; static DisabledPipelineHook instance; return instance.addRef(); } // ======================================================================================= ReaderCapabilityTable::ReaderCapabilityTable( kj::Array>> table) : table(kj::mv(table)) { setGlobalBrokenCapFactoryForLayoutCpp(brokenCapFactory); } kj::Maybe> ReaderCapabilityTable::extractCap(uint index) { if (index < table.size()) { return table[index].map([](kj::Own& cap) { return cap->addRef(); }); } else { return nullptr; } } BuilderCapabilityTable::BuilderCapabilityTable() { setGlobalBrokenCapFactoryForLayoutCpp(brokenCapFactory); } kj::Maybe> BuilderCapabilityTable::extractCap(uint index) { if (index < table.size()) { return table[index].map([](kj::Own& cap) { return cap->addRef(); }); } else { return nullptr; } } uint BuilderCapabilityTable::injectCap(kj::Own&& cap) { uint result = table.size(); table.add(kj::mv(cap)); return result; } void BuilderCapabilityTable::dropCap(uint index) { KJ_ASSERT(index < table.size(), "Invalid capability descriptor in message.") { return; } table[index] = nullptr; } // ======================================================================================= // CapabilityServerSet namespace _ { // private Capability::Client CapabilityServerSetBase::addInternal( kj::Own&& server, void* ptr) { return Capability::Client(kj::refcounted(kj::mv(server), *this, ptr)); } kj::Promise CapabilityServerSetBase::getLocalServerInternal(Capability::Client& client) { ClientHook* hook = client.hook.get(); // Get the most-resolved-so-far version of the hook. for (;;) { KJ_IF_MAYBE(h, hook->getResolved()) { hook = h; } else { break; } } // Try to unwrap that. if (hook->getBrand() == &LocalClient::BRAND) { KJ_IF_MAYBE(promise, kj::downcast(*hook).getLocalServer(*this)) { // This is definitely a member of our set and will resolve to non-null. We just have to wait // for any existing streaming calls to complete. return kj::mv(*promise); } } // OK, the capability isn't part of this set. KJ_IF_MAYBE(p, hook->whenMoreResolved()) { // This hook is an unresolved promise. It might resolve eventually to a local server, so wait // for it. return p->attach(hook->addRef()) .then([this](kj::Own&& resolved) { Capability::Client client(kj::mv(resolved)); return getLocalServerInternal(client); }); } else { // Cap is settled, so it definitely will never resolve to a member of this set. return kj::implicitCast(nullptr); } } } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/common.h0000644000175000017500000006636114731562162020316 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file contains types which are intended to help detect incorrect usage at compile // time, but should then be optimized down to basic primitives (usually, integers) by the // compiler. #pragma once #include #include #include #include // work-around macro conflict with `VOID` #if CAPNP_DEBUG_TYPES #include #endif #if !defined(CAPNP_HEADER_WARNINGS) || !CAPNP_HEADER_WARNINGS #define CAPNP_BEGIN_HEADER KJ_BEGIN_SYSTEM_HEADER #define CAPNP_END_HEADER KJ_END_SYSTEM_HEADER #else #define CAPNP_BEGIN_HEADER #define CAPNP_END_HEADER #endif CAPNP_BEGIN_HEADER namespace capnp { #define CAPNP_VERSION_MAJOR 1 #define CAPNP_VERSION_MINOR 1 #define CAPNP_VERSION_MICRO 0 #define CAPNP_VERSION \ (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) #ifndef CAPNP_LITE #define CAPNP_LITE 0 #endif #if CAPNP_TESTING_CAPNP // defined in Cap'n Proto's own unit tests; others should not define this #define CAPNP_DEPRECATED(reason) #else #define CAPNP_DEPRECATED KJ_DEPRECATED #endif typedef unsigned int uint; struct Void { // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves // differently from other types. inline constexpr bool operator==(Void other) const { return true; } inline constexpr bool operator!=(Void other) const { return false; } }; static constexpr Void VOID = Void(); // Constant value for `Void`, which is an empty struct. inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; } struct Text; struct Data; enum class Kind: uint8_t { PRIMITIVE, BLOB, ENUM, STRUCT, UNION, INTERFACE, LIST, OTHER // Some other type which is often a type parameter to Cap'n Proto templates, but which needs // special handling. This includes types like AnyPointer, Dynamic*, etc. }; enum class Style: uint8_t { PRIMITIVE, POINTER, // other than struct STRUCT, CAPABILITY }; enum class ElementSize: uint8_t { // Size of a list element. VOID = 0, BIT = 1, BYTE = 2, TWO_BYTES = 3, FOUR_BYTES = 4, EIGHT_BYTES = 5, POINTER = 6, INLINE_COMPOSITE = 7 }; enum class PointerType { // Various wire types a pointer field can take NULL_, // Should be NULL, but that's #defined in stddef.h STRUCT, LIST, CAPABILITY }; namespace schemas { template struct EnumInfo; } // namespace schemas namespace _ { // private template struct Kind_; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::PRIMITIVE; }; template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; template <> struct Kind_ { static constexpr Kind kind = Kind::BLOB; }; template struct Kind_> { static constexpr Kind kind = Kind::STRUCT; }; template struct Kind_> { static constexpr Kind kind = Kind::INTERFACE; }; template struct Kind_::IsEnum>> { static constexpr Kind kind = Kind::ENUM; }; } // namespace _ (private) template ::kind> inline constexpr Kind kind() { // This overload of kind() matches types which have a Kind_ specialization. return k; } #if _MSC_VER && !defined(__clang__) #define CAPNP_KIND(T) ::capnp::_::Kind_::kind // Avoid constexpr methods in MSVC (it remains buggy in many situations). #else // _MSC_VER #define CAPNP_KIND(T) ::capnp::kind() // Use this macro rather than kind() in any code which must work in MSVC. #endif // _MSC_VER, else #if !CAPNP_LITE template ()> inline constexpr Style style() { return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE : k == Kind::STRUCT ? Style::STRUCT : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; } #endif // !CAPNP_LITE template struct List; #if _MSC_VER && !defined(__clang__) template struct List {}; // For some reason, without this declaration, MSVC will error out on some uses of List // claiming that "T" -- as used in the default initializer for the second template param, "k" -- // is not defined. I do not understand this error, but adding this empty default declaration fixes // it. #endif template struct ListElementType_; template struct ListElementType_> { typedef T Type; }; template using ListElementType = typename ListElementType_::Type; namespace _ { // private template struct Kind_> { static constexpr Kind kind = Kind::LIST; }; } // namespace _ (private) template struct ReaderFor_ { typedef typename T::Reader Type; }; template struct ReaderFor_ { typedef T Type; }; template struct ReaderFor_ { typedef T Type; }; template struct ReaderFor_ { typedef typename T::Client Type; }; template using ReaderFor = typename ReaderFor_::Type; // The type returned by List::Reader::operator[]. template struct BuilderFor_ { typedef typename T::Builder Type; }; template struct BuilderFor_ { typedef T Type; }; template struct BuilderFor_ { typedef T Type; }; template struct BuilderFor_ { typedef typename T::Client Type; }; template using BuilderFor = typename BuilderFor_::Type; // The type returned by List::Builder::operator[]. template struct PipelineFor_ { typedef typename T::Pipeline Type;}; template struct PipelineFor_ { typedef typename T::Client Type; }; template using PipelineFor = typename PipelineFor_::Type; template struct TypeIfEnum_; template struct TypeIfEnum_ { typedef T Type; }; template using TypeIfEnum = typename TypeIfEnum_>::Type; template using FromReader = typename kj::Decay::Reads; // FromReader = MyType (for any Cap'n Proto type). template using FromBuilder = typename kj::Decay::Builds; // FromBuilder = MyType (for any Cap'n Proto type). template using FromPipeline = typename kj::Decay::Pipelines; // FromBuilder = MyType (for any Cap'n Proto type). template using FromClient = typename kj::Decay::Calls; // FromReader = MyType (for any Cap'n Proto interface type). template using FromServer = typename kj::Decay::Serves; // FromBuilder = MyType (for any Cap'n Proto interface type). template struct FromAny_; template struct FromAny_>> { using Type = FromReader; }; template struct FromAny_>> { using Type = FromBuilder; }; template struct FromAny_>> { using Type = FromPipeline; }; // Note that T::Client is covered by FromReader template struct FromAny_, kj::VoidSfinae>> { using Type = FromServer; }; template struct FromAny_::kind == Kind::PRIMITIVE || _::Kind_::kind == Kind::ENUM>> { // TODO(msvc): Ideally the EnableIf condition would be `style() == Style::PRIMITIVE`, but MSVC // cannot yet use style() in this constexpr context. using Type = kj::Decay; }; template using FromAny = typename FromAny_::Type; // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: // // Foo::Reader -> Foo // Foo::Builder -> Foo // Foo::Pipeline -> Foo // Foo::Client -> Foo // Own -> Foo // uint32_t -> uint32_t namespace _ { // private template struct PointerHelpers; #if _MSC_VER && !defined(__clang__) template struct PointerHelpers {}; // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers // claiming that "T" -- as used in the default initializer for the second template param, "k" -- // is not defined. I do not understand this error, but adding this empty default declaration fixes // it. #endif } // namespace _ (private) struct MessageSize { // Size of a message. Every struct and list type has a method `.totalSize()` that returns this. uint64_t wordCount; uint capCount; inline constexpr MessageSize operator+(const MessageSize& other) const { return { wordCount + other.wordCount, capCount + other.capCount }; } }; // ======================================================================================= // Raw memory types and measures using kj::byte; class word { // word is an opaque type with size of 64 bits. This type is useful only to make pointer // arithmetic clearer. Since the contents are private, the only way to access them is to first // reinterpret_cast to some other pointer type. // // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of // aliasing rules. // // A pointer of type word* should always be word-aligned even if won't actually be dereferenced // as that type. public: word() = default; private: uint64_t content KJ_UNUSED_MEMBER; #if __GNUC__ < 8 || __clang__ // GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed // the copy constructor. We don't want to disable the warning because it's a useful warning and // we'd have to disable it for all applications that include this header. Instead we allow `word` // to be copyable on GCC. KJ_DISALLOW_COPY_AND_MOVE(word); #endif }; static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); #if CAPNP_DEBUG_TYPES // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are // used. All the code should still operate exactly the same, we just lose compile-time checking. // Note that this will also change symbol names, so it's important that the library and any clients // be compiled with the same setting here. // // We disable this by default to reduce symbol name size and avoid any possibility of the compiler // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this // during development and testing. namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } template using BitCountN = kj::Quantity(), T>, _::BitLabel>; template using ByteCountN = kj::Quantity(), T>, byte>; template using WordCountN = kj::Quantity(), T>, word>; template using ElementCountN = kj::Quantity(), T>, _::ElementLabel>; template using WirePointerCountN = kj::Quantity(), T>, _::WirePointer>; typedef BitCountN<8, uint8_t> BitCount8; typedef BitCountN<16, uint16_t> BitCount16; typedef BitCountN<32, uint32_t> BitCount32; typedef BitCountN<64, uint64_t> BitCount64; typedef BitCountN BitCount; typedef ByteCountN<8, uint8_t> ByteCount8; typedef ByteCountN<16, uint16_t> ByteCount16; typedef ByteCountN<32, uint32_t> ByteCount32; typedef ByteCountN<64, uint64_t> ByteCount64; typedef ByteCountN ByteCount; typedef WordCountN<8, uint8_t> WordCount8; typedef WordCountN<16, uint16_t> WordCount16; typedef WordCountN<32, uint32_t> WordCount32; typedef WordCountN<64, uint64_t> WordCount64; typedef WordCountN WordCount; typedef ElementCountN<8, uint8_t> ElementCount8; typedef ElementCountN<16, uint16_t> ElementCount16; typedef ElementCountN<32, uint32_t> ElementCount32; typedef ElementCountN<64, uint64_t> ElementCount64; typedef ElementCountN ElementCount; typedef WirePointerCountN<8, uint8_t> WirePointerCount8; typedef WirePointerCountN<16, uint16_t> WirePointerCount16; typedef WirePointerCountN<32, uint32_t> WirePointerCount32; typedef WirePointerCountN<64, uint64_t> WirePointerCount64; typedef WirePointerCountN WirePointerCount; template using BitsPerElementN = decltype(BitCountN() / ElementCountN()); template using BytesPerElementN = decltype(ByteCountN() / ElementCountN()); template using WordsPerElementN = decltype(WordCountN() / ElementCountN()); template using PointersPerElementN = decltype(WirePointerCountN() / ElementCountN()); using kj::bounded; using kj::unbound; using kj::unboundAs; using kj::unboundMax; using kj::unboundMaxBits; using kj::assertMax; using kj::assertMaxBits; using kj::upgradeBound; using kj::ThrowOverflow; using kj::assumeBits; using kj::assumeMax; using kj::subtractChecked; using kj::trySubtract; template inline constexpr U* operator+(U* ptr, kj::Quantity offset) { return ptr + unbound(offset / kj::unit>()); } template inline constexpr const U* operator+(const U* ptr, kj::Quantity offset) { return ptr + unbound(offset / kj::unit>()); } template inline constexpr U* operator+=(U*& ptr, kj::Quantity offset) { return ptr = ptr + unbound(offset / kj::unit>()); } template inline constexpr const U* operator+=(const U*& ptr, kj::Quantity offset) { return ptr = ptr + unbound(offset / kj::unit>()); } template inline constexpr U* operator-(U* ptr, kj::Quantity offset) { return ptr - unbound(offset / kj::unit>()); } template inline constexpr const U* operator-(const U* ptr, kj::Quantity offset) { return ptr - unbound(offset / kj::unit>()); } template inline constexpr U* operator-=(U*& ptr, kj::Quantity offset) { return ptr = ptr - unbound(offset / kj::unit>()); } template inline constexpr const U* operator-=(const U*& ptr, kj::Quantity offset) { return ptr = ptr - unbound(offset / kj::unit>()); } constexpr auto BITS = kj::unit>(); constexpr auto BYTES = kj::unit>(); constexpr auto WORDS = kj::unit>(); constexpr auto ELEMENTS = kj::unit>(); constexpr auto POINTERS = kj::unit>(); constexpr auto ZERO = kj::bounded<0>(); constexpr auto ONE = kj::bounded<1>(); // GCC 4.7 actually gives unused warnings on these constants in opt mode... constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES; constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS; constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS; constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS; constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS; constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS; constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. typedef WordCountN SegmentWordCount; typedef ElementCountN ListElementCount; typedef WordCountN StructDataWordCount; typedef WirePointerCountN StructPointerCount; typedef ByteCountN BlobSize; constexpr auto MAX_SEGMENT_WORDS = bounded()>() * WORDS; constexpr auto MAX_LIST_ELEMENTS = bounded()>() * ELEMENTS; constexpr auto MAX_STUCT_DATA_WORDS = bounded()>() * WORDS; constexpr auto MAX_STRUCT_POINTER_COUNT = bounded()>() * POINTERS; using StructDataBitCount = decltype(WordCountN() * BITS_PER_WORD); // Number of bits in a Struct data segment (should come out to BitCountN<22>). using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS)); using StructPointerOffset = StructPointerCount; // Type of a field offset. inline StructDataOffset assumeDataOffset(uint32_t offset) { return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS), bounded(offset) * ELEMENTS); } inline StructPointerOffset assumePointerOffset(uint32_t offset) { return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS); } constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits() - 1; typedef kj::Quantity, byte> TextSize; // Not including NUL terminator. template inline KJ_CONSTEXPR() decltype(bounded() * BYTES / ELEMENTS) bytesPerElement() { return bounded() * BYTES / ELEMENTS; } template inline KJ_CONSTEXPR() decltype(bounded() * BITS / ELEMENTS) bitsPerElement() { return bounded() * BITS / ELEMENTS; } template inline constexpr kj::Quantity, T> intervalLength(const T* a, const T* b, kj::Quantity, T>) { return kj::assumeMax(b - a) * kj::unit, T>>(); } template inline constexpr kj::ArrayPtr arrayPtr(const U* ptr, kj::Quantity size) { return kj::ArrayPtr(ptr, unbound(size / kj::unit>())); } template inline constexpr kj::ArrayPtr arrayPtr(U* ptr, kj::Quantity size) { return kj::ArrayPtr(ptr, unbound(size / kj::unit>())); } #else template using BitCountN = T; template using ByteCountN = T; template using WordCountN = T; template using ElementCountN = T; template using WirePointerCountN = T; // XXX typedef BitCountN<8, uint8_t> BitCount8; typedef BitCountN<16, uint16_t> BitCount16; typedef BitCountN<32, uint32_t> BitCount32; typedef BitCountN<64, uint64_t> BitCount64; typedef BitCountN BitCount; typedef ByteCountN<8, uint8_t> ByteCount8; typedef ByteCountN<16, uint16_t> ByteCount16; typedef ByteCountN<32, uint32_t> ByteCount32; typedef ByteCountN<64, uint64_t> ByteCount64; typedef ByteCountN ByteCount; typedef WordCountN<8, uint8_t> WordCount8; typedef WordCountN<16, uint16_t> WordCount16; typedef WordCountN<32, uint32_t> WordCount32; typedef WordCountN<64, uint64_t> WordCount64; typedef WordCountN WordCount; typedef ElementCountN<8, uint8_t> ElementCount8; typedef ElementCountN<16, uint16_t> ElementCount16; typedef ElementCountN<32, uint32_t> ElementCount32; typedef ElementCountN<64, uint64_t> ElementCount64; typedef ElementCountN ElementCount; typedef WirePointerCountN<8, uint8_t> WirePointerCount8; typedef WirePointerCountN<16, uint16_t> WirePointerCount16; typedef WirePointerCountN<32, uint32_t> WirePointerCount32; typedef WirePointerCountN<64, uint64_t> WirePointerCount64; typedef WirePointerCountN WirePointerCount; template using BitsPerElementN = decltype(BitCountN() / ElementCountN()); template using BytesPerElementN = decltype(ByteCountN() / ElementCountN()); template using WordsPerElementN = decltype(WordCountN() / ElementCountN()); template using PointersPerElementN = decltype(WirePointerCountN() / ElementCountN()); using kj::ThrowOverflow; // YYY template inline constexpr uint bounded() { return i; } template inline constexpr T bounded(T i) { return i; } template inline constexpr T unbound(T i) { return i; } template inline constexpr T unboundAs(U i) { return i; } template inline constexpr uint unboundMax(T i) { return i; } template inline constexpr uint unboundMaxBits(T i) { return i; } template inline T assertMax(T value, ErrorFunc&& func) { if (KJ_UNLIKELY(value > newMax)) func(); return value; } template inline T assertMax(uint newMax, T value, ErrorFunc&& func) { if (KJ_UNLIKELY(value > newMax)) func(); return value; } template inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) { if (KJ_UNLIKELY(value > kj::maxValueForBits())) func(); return value; } template inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) { if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func(); return value; } template inline constexpr T upgradeBound(U i) { return i; } template inline constexpr T assumeBits(T i) { return i; } template inline constexpr T assumeMax(T i) { return i; } template inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc()) -> decltype(a - b) { if (b > a) errorFunc(); return a - b; } template inline auto trySubtract(T a, U b) -> kj::Maybe { if (b > a) { return nullptr; } else { return a - b; } } constexpr uint BITS = 1; constexpr uint BYTES = 1; constexpr uint WORDS = 1; constexpr uint ELEMENTS = 1; constexpr uint POINTERS = 1; constexpr uint ZERO = 0; constexpr uint ONE = 1; // GCC 4.7 actually gives unused warnings on these constants in opt mode... constexpr uint BITS_PER_BYTE KJ_UNUSED = 8; constexpr uint BITS_PER_WORD KJ_UNUSED = 64; constexpr uint BYTES_PER_WORD KJ_UNUSED = 8; constexpr uint BITS_PER_POINTER KJ_UNUSED = 64; constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8; constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1; // XXX constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. typedef WordCountN SegmentWordCount; typedef ElementCountN ListElementCount; typedef WordCountN StructDataWordCount; typedef WirePointerCountN StructPointerCount; typedef ByteCountN BlobSize; // YYY constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits(); constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits(); constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits(); constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits(); typedef uint StructDataBitCount; typedef uint StructDataOffset; typedef uint StructPointerOffset; inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; } inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; } constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits() - 1; typedef uint TextSize; template inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); } template inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; } template inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) { return b - a; } template inline constexpr kj::ArrayPtr arrayPtr(const U* ptr, T size) { return kj::arrayPtr(ptr, size); } template inline constexpr kj::ArrayPtr arrayPtr(U* ptr, T size) { return kj::arrayPtr(ptr, size); } #endif } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/layout-test.c++0000644000175000017500000004300314527152321021420 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "layout.h" #include "message.h" #include "arena.h" #include #if CAPNP_DEBUG_TYPES namespace kj { template String KJ_STRINGIFY(kj::Quantity value) { return kj::str(unboundAs(value / kj::unit>())); } // Hack: Allow direct comparisons and multiplications so that we don't have to rewrite the code // below. template inline constexpr Bounded<65535, T> operator*(uint a, Bounded b) { return assumeBits<16>(a * unbound(b)); } template inline constexpr Bounded<65535, uint> operator*(uint a, BoundedConst) { return assumeBits<16>(a * b); } } #endif namespace capnp { namespace _ { // private namespace { TEST(WireFormat, SimpleRawDataStruct) { AlignedData<2> data = {{ // Struct ref, offset = 1, dataSize = 1, pointerCount = 0 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Content for the data section. 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }}; StructReader reader = PointerReader::getRootUnchecked(data.words).getStruct(nullptr); EXPECT_EQ(0xefcdab8967452301ull, reader.getDataField(0 * ELEMENTS)); EXPECT_EQ(0u, reader.getDataField(1 * ELEMENTS)); EXPECT_EQ(0x67452301u, reader.getDataField(0 * ELEMENTS)); EXPECT_EQ(0xefcdab89u, reader.getDataField(1 * ELEMENTS)); EXPECT_EQ(0u, reader.getDataField(2 * ELEMENTS)); EXPECT_EQ(0x2301u, reader.getDataField(0 * ELEMENTS)); EXPECT_EQ(0x6745u, reader.getDataField(1 * ELEMENTS)); EXPECT_EQ(0xab89u, reader.getDataField(2 * ELEMENTS)); EXPECT_EQ(0xefcdu, reader.getDataField(3 * ELEMENTS)); EXPECT_EQ(0u, reader.getDataField(4 * ELEMENTS)); EXPECT_EQ(321u ^ 0xefcdab8967452301ull, reader.getDataField(0 * ELEMENTS, 321u)); EXPECT_EQ(321u ^ 0x67452301u, reader.getDataField(0 * ELEMENTS, 321u)); EXPECT_EQ(321u ^ 0x2301u, reader.getDataField(0 * ELEMENTS, 321u)); EXPECT_EQ(321u, reader.getDataField(1 * ELEMENTS, 321u)); EXPECT_EQ(321u, reader.getDataField(2 * ELEMENTS, 321u)); EXPECT_EQ(321u, reader.getDataField(4 * ELEMENTS, 321u)); // Bits EXPECT_TRUE (reader.getDataField(0 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(1 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(2 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(3 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(4 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(5 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(6 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(7 * ELEMENTS)); EXPECT_TRUE (reader.getDataField( 8 * ELEMENTS)); EXPECT_TRUE (reader.getDataField( 9 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(10 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(11 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(12 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(13 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(14 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(15 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(63 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(64 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(0 * ELEMENTS, false)); EXPECT_FALSE(reader.getDataField(1 * ELEMENTS, false)); EXPECT_TRUE (reader.getDataField(63 * ELEMENTS, false)); EXPECT_FALSE(reader.getDataField(64 * ELEMENTS, false)); EXPECT_FALSE(reader.getDataField(0 * ELEMENTS, true)); EXPECT_TRUE (reader.getDataField(1 * ELEMENTS, true)); EXPECT_FALSE(reader.getDataField(63 * ELEMENTS, true)); EXPECT_TRUE (reader.getDataField(64 * ELEMENTS, true)); } static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0}}; static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0}}; static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * POINTERS); static void setupStruct(StructBuilder builder) { builder.setDataField(0 * ELEMENTS, 0x1011121314151617ull); builder.setDataField(2 * ELEMENTS, 0x20212223u); builder.setDataField(6 * ELEMENTS, 0x3031u); builder.setDataField(14 * ELEMENTS, 0x40u); builder.setDataField(120 * ELEMENTS, false); builder.setDataField(121 * ELEMENTS, false); builder.setDataField(122 * ELEMENTS, true); builder.setDataField(123 * ELEMENTS, false); builder.setDataField(124 * ELEMENTS, true); builder.setDataField(125 * ELEMENTS, true); builder.setDataField(126 * ELEMENTS, true); builder.setDataField(127 * ELEMENTS, false); { StructBuilder subStruct = builder.getPointerField(0 * POINTERS).initStruct( StructSize(1 * WORDS, 0 * POINTERS)); subStruct.setDataField(0 * ELEMENTS, 123); } { ListBuilder list = builder.getPointerField(1 * POINTERS) .initList(ElementSize::FOUR_BYTES, 3 * ELEMENTS); EXPECT_EQ(3 * ELEMENTS, list.size()); list.setDataElement(0 * ELEMENTS, 200); list.setDataElement(1 * ELEMENTS, 201); list.setDataElement(2 * ELEMENTS, 202); } { ListBuilder list = builder.getPointerField(2 * POINTERS).initStructList( 4 * ELEMENTS, STRUCTLIST_ELEMENT_SIZE); EXPECT_EQ(4 * ELEMENTS, list.size()); for (int i = 0; i < 4; i++) { StructBuilder element = list.getStructElement(i * ELEMENTS); element.setDataField(0 * ELEMENTS, 300 + i); element.getPointerField(0 * POINTERS) .initStruct(StructSize(1 * WORDS, 0 * POINTERS)) .setDataField(0 * ELEMENTS, 400 + i); } } { ListBuilder list = builder.getPointerField(3 * POINTERS) .initList(ElementSize::POINTER, 5 * ELEMENTS); EXPECT_EQ(5 * ELEMENTS, list.size()); for (uint i = 0; i < 5; i++) { ListBuilder element = list.getPointerElement(i * ELEMENTS) .initList(ElementSize::TWO_BYTES, (i + 1) * ELEMENTS); EXPECT_EQ((i + 1) * ELEMENTS, element.size()); for (uint j = 0; j <= i; j++) { element.setDataElement(j * ELEMENTS, 500 + j); } } } } static void checkStruct(StructBuilder builder) { EXPECT_EQ(0x1011121314151617ull, builder.getDataField(0 * ELEMENTS)); EXPECT_EQ(0x20212223u, builder.getDataField(2 * ELEMENTS)); EXPECT_EQ(0x3031u, builder.getDataField(6 * ELEMENTS)); EXPECT_EQ(0x40u, builder.getDataField(14 * ELEMENTS)); EXPECT_FALSE(builder.getDataField(120 * ELEMENTS)); EXPECT_FALSE(builder.getDataField(121 * ELEMENTS)); EXPECT_TRUE (builder.getDataField(122 * ELEMENTS)); EXPECT_FALSE(builder.getDataField(123 * ELEMENTS)); EXPECT_TRUE (builder.getDataField(124 * ELEMENTS)); EXPECT_TRUE (builder.getDataField(125 * ELEMENTS)); EXPECT_TRUE (builder.getDataField(126 * ELEMENTS)); EXPECT_FALSE(builder.getDataField(127 * ELEMENTS)); { StructBuilder subStruct = builder.getPointerField(0 * POINTERS).getStruct( StructSize(1 * WORDS, 0 * POINTERS), SUBSTRUCT_DEFAULT.words); EXPECT_EQ(123u, subStruct.getDataField(0 * ELEMENTS)); } { ListBuilder list = builder.getPointerField(1 * POINTERS) .getList(ElementSize::FOUR_BYTES, nullptr); ASSERT_EQ(3 * ELEMENTS, list.size()); EXPECT_EQ(200, list.getDataElement(0 * ELEMENTS)); EXPECT_EQ(201, list.getDataElement(1 * ELEMENTS)); EXPECT_EQ(202, list.getDataElement(2 * ELEMENTS)); } { ListBuilder list = builder.getPointerField(2 * POINTERS) .getStructList(STRUCTLIST_ELEMENT_SIZE, nullptr); ASSERT_EQ(4 * ELEMENTS, list.size()); for (int i = 0; i < 4; i++) { StructBuilder element = list.getStructElement(i * ELEMENTS); EXPECT_EQ(300 + i, element.getDataField(0 * ELEMENTS)); EXPECT_EQ(400 + i, element.getPointerField(0 * POINTERS) .getStruct(StructSize(1 * WORDS, 0 * POINTERS), STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words) .getDataField(0 * ELEMENTS)); } } { ListBuilder list = builder.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr); ASSERT_EQ(5 * ELEMENTS, list.size()); for (uint i = 0; i < 5; i++) { ListBuilder element = list.getPointerElement(i * ELEMENTS) .getList(ElementSize::TWO_BYTES, nullptr); ASSERT_EQ((i + 1) * ELEMENTS, element.size()); for (uint j = 0; j <= i; j++) { EXPECT_EQ(500u + j, element.getDataElement(j * ELEMENTS)); } } } } static void checkStruct(StructReader reader) { EXPECT_EQ(0x1011121314151617ull, reader.getDataField(0 * ELEMENTS)); EXPECT_EQ(0x20212223u, reader.getDataField(2 * ELEMENTS)); EXPECT_EQ(0x3031u, reader.getDataField(6 * ELEMENTS)); EXPECT_EQ(0x40u, reader.getDataField(14 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(120 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(121 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(122 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(123 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(124 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(125 * ELEMENTS)); EXPECT_TRUE (reader.getDataField(126 * ELEMENTS)); EXPECT_FALSE(reader.getDataField(127 * ELEMENTS)); { StructReader subStruct = reader.getPointerField(0 * POINTERS) .getStruct(SUBSTRUCT_DEFAULT.words); EXPECT_EQ(123u, subStruct.getDataField(0 * ELEMENTS)); } { ListReader list = reader.getPointerField(1 * POINTERS).getList(ElementSize::FOUR_BYTES, nullptr); ASSERT_EQ(3 * ELEMENTS, list.size()); EXPECT_EQ(200, list.getDataElement(0 * ELEMENTS)); EXPECT_EQ(201, list.getDataElement(1 * ELEMENTS)); EXPECT_EQ(202, list.getDataElement(2 * ELEMENTS)); } { ListReader list = reader.getPointerField(2 * POINTERS) .getList(ElementSize::INLINE_COMPOSITE, nullptr); ASSERT_EQ(4 * ELEMENTS, list.size()); for (int i = 0; i < 4; i++) { StructReader element = list.getStructElement(i * ELEMENTS); EXPECT_EQ(300 + i, element.getDataField(0 * ELEMENTS)); EXPECT_EQ(400 + i, element.getPointerField(0 * POINTERS) .getStruct(STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words) .getDataField(0 * ELEMENTS)); } } { ListReader list = reader.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr); ASSERT_EQ(5 * ELEMENTS, list.size()); for (uint i = 0; i < 5; i++) { ListReader element = list.getPointerElement(i * ELEMENTS) .getList(ElementSize::TWO_BYTES, nullptr); ASSERT_EQ((i + 1) * ELEMENTS, element.size()); for (uint j = 0; j <= i; j++) { EXPECT_EQ(500u + j, element.getDataElement(j * ELEMENTS)); } } } } TEST(WireFormat, StructRoundTrip_OneSegment) { MallocMessageBuilder message; BuilderArena arena(&message); auto allocation = arena.allocate(1 * WORDS); SegmentBuilder* segment = allocation.segment; word* rootLocation = allocation.words; StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation) .initStruct(StructSize(2 * WORDS, 4 * POINTERS)); setupStruct(builder); // word count: // 1 root pointer // 6 root struct // 1 sub message // 2 3-element int32 list // 13 struct list // 1 tag // 12 4x struct // 1 data section // 1 pointer section // 1 sub-struct // 11 list list // 5 pointers to sub-lists // 6 sub-lists (4x 1 word, 1x 2 words) // ----- // 34 kj::ArrayPtr> segments = arena.getSegmentsForOutput(); ASSERT_EQ(1u, segments.size()); EXPECT_EQ(34u, segments[0].size()); checkStruct(builder); checkStruct(builder.asReader()); checkStruct(PointerReader::getRootUnchecked(segment->getStartPtr()).getStruct(nullptr)); checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4) .getStruct(nullptr)); } TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) { MallocMessageBuilder message(0, AllocationStrategy::FIXED_SIZE); BuilderArena arena(&message); auto allocation = arena.allocate(1 * WORDS); SegmentBuilder* segment = allocation.segment; word* rootLocation = allocation.words; StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation) .initStruct(StructSize(2 * WORDS, 4 * POINTERS)); setupStruct(builder); // Verify that we made 15 segments. kj::ArrayPtr> segments = arena.getSegmentsForOutput(); ASSERT_EQ(15u, segments.size()); // Check that each segment has the expected size. Recall that the first word of each segment will // actually be a pointer to the first thing allocated within that segment. EXPECT_EQ( 1u, segments[ 0].size()); // root ref EXPECT_EQ( 7u, segments[ 1].size()); // root struct EXPECT_EQ( 2u, segments[ 2].size()); // sub-struct EXPECT_EQ( 3u, segments[ 3].size()); // 3-element int32 list EXPECT_EQ(10u, segments[ 4].size()); // struct list EXPECT_EQ( 2u, segments[ 5].size()); // struct list substruct 1 EXPECT_EQ( 2u, segments[ 6].size()); // struct list substruct 2 EXPECT_EQ( 2u, segments[ 7].size()); // struct list substruct 3 EXPECT_EQ( 2u, segments[ 8].size()); // struct list substruct 4 EXPECT_EQ( 6u, segments[ 9].size()); // list list EXPECT_EQ( 2u, segments[10].size()); // list list sublist 1 EXPECT_EQ( 2u, segments[11].size()); // list list sublist 2 EXPECT_EQ( 2u, segments[12].size()); // list list sublist 3 EXPECT_EQ( 2u, segments[13].size()); // list list sublist 4 EXPECT_EQ( 3u, segments[14].size()); // list list sublist 5 checkStruct(builder); checkStruct(builder.asReader()); checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4) .getStruct(nullptr)); } TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) { MallocMessageBuilder message(8, AllocationStrategy::FIXED_SIZE); BuilderArena arena(&message); auto allocation = arena.allocate(1 * WORDS); SegmentBuilder* segment = allocation.segment; word* rootLocation = allocation.words; StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation) .initStruct(StructSize(2 * WORDS, 4 * POINTERS)); setupStruct(builder); // Verify that we made 6 segments. kj::ArrayPtr> segments = arena.getSegmentsForOutput(); ASSERT_EQ(6u, segments.size()); // Check that each segment has the expected size. Recall that each object will be prefixed by an // extra word if its parent is in a different segment. EXPECT_EQ( 8u, segments[0].size()); // root ref + struct + sub EXPECT_EQ( 3u, segments[1].size()); // 3-element int32 list EXPECT_EQ(10u, segments[2].size()); // struct list EXPECT_EQ( 8u, segments[3].size()); // struct list substructs EXPECT_EQ( 8u, segments[4].size()); // list list + sublist 1,2 EXPECT_EQ( 7u, segments[5].size()); // list list sublist 3,4,5 checkStruct(builder); checkStruct(builder.asReader()); checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4) .getStruct(nullptr)); } inline bool isNan(float f) { return f != f; } inline bool isNan(double f) { return f != f; } TEST(WireFormat, NanPatching) { EXPECT_EQ(0x7fc00000u, mask(kj::nan(), 0)); EXPECT_TRUE(isNan(unmask(0x7fc00000u, 0))); EXPECT_TRUE(isNan(unmask(0x7fc00001u, 0))); EXPECT_TRUE(isNan(unmask(0x7fc00005u, 0))); EXPECT_EQ(0x7fc00000u, mask(unmask(0x7fc00000u, 0), 0)); EXPECT_EQ(0x7ff8000000000000ull, mask((double)kj::nan(), 0)); EXPECT_TRUE(isNan(unmask(0x7ff8000000000000ull, 0))); EXPECT_TRUE(isNan(unmask(0x7ff8000000000001ull, 0))); EXPECT_TRUE(isNan(unmask(0x7ff8000000000005ull, 0))); EXPECT_EQ(0x7ff8000000000000ull, mask(unmask(0x7ff8000000000000ull, 0), 0)); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/pointer-helpers.h0000644000175000017500000001434114712011043022117 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "layout.h" #include "list.h" CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private // PointerHelpers is a template class that assists in wrapping/unwrapping the low-level types in // layout.h with the high-level public API and generated types. This way, the code generator // and other templates do not have to specialize on each kind of pointer. template struct PointerHelpers { static inline typename T::Reader get(PointerReader reader, const word* defaultValue = nullptr) { return typename T::Reader(reader.getStruct(defaultValue)); } static inline typename T::Builder get(PointerBuilder builder, const word* defaultValue = nullptr) { return typename T::Builder(builder.getStruct(structSize(), defaultValue)); } static inline void set(PointerBuilder builder, typename T::Reader value) { builder.setStruct(value._reader); } static inline void setCanonical(PointerBuilder builder, typename T::Reader value) { builder.setStruct(value._reader, true); } static inline typename T::Builder init(PointerBuilder builder) { return typename T::Builder(builder.initStruct(structSize())); } static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } static inline _::StructReader getInternalReader(const typename T::Reader& reader) { return reader._reader; } static inline _::StructBuilder getInternalBuilder(typename T::Builder&& builder) { return builder._builder; } }; template struct PointerHelpers, Kind::LIST> { static inline typename List::Reader get(PointerReader reader, const word* defaultValue = nullptr) { return typename List::Reader(List::getFromPointer(reader, defaultValue)); } static inline typename List::Builder get(PointerBuilder builder, const word* defaultValue = nullptr) { return typename List::Builder(List::getFromPointer(builder, defaultValue)); } static inline void set(PointerBuilder builder, typename List::Reader value) { builder.setList(value.reader); } static inline void setCanonical(PointerBuilder builder, typename List::Reader value) { builder.setList(value.reader, true); } static void set(PointerBuilder builder, kj::ArrayPtr> value) { auto l = init(builder, value.size()); uint i = 0; for (auto& element: value) { l.set(i++, element); } } static inline typename List::Builder init(PointerBuilder builder, uint size) { return typename List::Builder(List::initPointer(builder, size)); } static inline void adopt(PointerBuilder builder, Orphan>&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan> disown(PointerBuilder builder) { return Orphan>(builder.disown()); } static inline _::ListReader getInternalReader(const typename List::Reader& reader) { return reader.reader; } static inline _::ListBuilder getInternalBuilder(typename List::Builder&& builder) { return builder.builder; } }; template struct PointerHelpers { static inline typename T::Reader get(PointerReader reader, const void* defaultValue = nullptr, uint defaultBytes = 0) { return reader.getBlob(defaultValue, bounded(defaultBytes) * BYTES); } static inline typename T::Builder get(PointerBuilder builder, const void* defaultValue = nullptr, uint defaultBytes = 0) { return builder.getBlob(defaultValue, bounded(defaultBytes) * BYTES); } static inline void set(PointerBuilder builder, typename T::Reader value) { builder.setBlob(value); } static inline void setCanonical(PointerBuilder builder, typename T::Reader value) { builder.setBlob(value); } static inline typename T::Builder init(PointerBuilder builder, uint size) { return builder.initBlob(bounded(size) * BYTES); } static inline void adopt(PointerBuilder builder, Orphan&& value) { builder.adopt(kj::mv(value.builder)); } static inline Orphan disown(PointerBuilder builder) { return Orphan(builder.disown()); } }; struct UncheckedMessage { typedef const word* Reader; }; template <> struct Kind_ { static constexpr Kind kind = Kind::OTHER; }; template <> struct PointerHelpers { // Reads an AnyPointer field as an unchecked message pointer. Requires that the containing // message is itself unchecked. This hack is currently private. It is used to locate default // values within encoded schemas. static inline const word* get(PointerReader reader) { return reader.getUnchecked(); } }; } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/endian-fallback-test.c++0000644000175000017500000000245114527152321023100 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // Test that the shift-based implementation of WireValue works. #define CAPNP_DISABLE_ENDIAN_DETECTION 1 #include "endian-test.c++" capnproto-c++-1.1.0/src/capnp/schema-test.c++0000644000175000017500000004410514712011043021336 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #include "schema.h" #include #include "test-util.h" // TODO(cleanup): Auto-generate stringification functions for union discriminants. namespace capnp { namespace schema { inline kj::String KJ_STRINGIFY(Type::Which which) { return kj::str(static_cast(which)); } } // namespace schema } // namespace capnp namespace capnp { namespace _ { // private namespace { TEST(Schema, Structs) { StructSchema schema = Schema::from(); EXPECT_EQ(typeId(), schema.getProto().getId()); EXPECT_TRUE(schema.getDependency(typeId()) == Schema::from()); EXPECT_TRUE(schema.getDependency(typeId()) != schema); EXPECT_TRUE(schema.getDependency(typeId()) == Schema::from()); EXPECT_TRUE(schema.getDependency(typeId()) == schema); EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId())); EXPECT_TRUE(schema.asStruct() == schema); EXPECT_NONFATAL_FAILURE(schema.asEnum()); EXPECT_NONFATAL_FAILURE(schema.asInterface()); ASSERT_EQ("TestAllTypes", schema.getUnqualifiedName()); ASSERT_EQ(schema.getFields().size(), schema.getProto().getStruct().getFields().size()); StructSchema::Field field = schema.getFields()[0]; EXPECT_EQ("voidField", field.getProto().getName()); EXPECT_TRUE(field.getContainingStruct() == schema); StructSchema::Field lookup = schema.getFieldByName("voidField"); EXPECT_TRUE(lookup == field); EXPECT_TRUE(lookup != schema.getFields()[1]); EXPECT_FALSE(lookup.getProto().getSlot().getHadExplicitDefault()); EXPECT_FALSE(schema.getFieldByName("int32Field").getProto().getSlot().getHadExplicitDefault()); EXPECT_TRUE(Schema::from().getFieldByName("int32Field") .getProto().getSlot().getHadExplicitDefault()); EXPECT_TRUE(schema.findFieldByName("noSuchField") == nullptr); EXPECT_TRUE(schema.findFieldByName("int32Field") != nullptr); EXPECT_TRUE(schema.findFieldByName("float32List") != nullptr); EXPECT_TRUE(schema.findFieldByName("dataList") != nullptr); EXPECT_TRUE(schema.findFieldByName("textField") != nullptr); EXPECT_TRUE(schema.findFieldByName("structField") != nullptr); } TEST(Schema, FieldLookupOutOfOrder) { // Tests that name lookup works correctly when the fields are defined out-of-order in the schema // file. auto schema = Schema::from().asStruct(); EXPECT_EQ("qux", schema.getFields()[0].getProto().getName()); EXPECT_EQ("grault", schema.getFields()[1].getProto().getName()); EXPECT_EQ("bar", schema.getFields()[2].getProto().getName()); EXPECT_EQ("foo", schema.getFields()[3].getProto().getName()); EXPECT_EQ("corge", schema.getFields()[4].getProto().getName()); EXPECT_EQ("waldo", schema.getFields()[5].getProto().getName()); EXPECT_EQ("quux", schema.getFields()[6].getProto().getName()); EXPECT_EQ("garply", schema.getFields()[7].getProto().getName()); EXPECT_EQ("baz", schema.getFields()[8].getProto().getName()); EXPECT_EQ(3, schema.getFieldByName("foo").getProto().getOrdinal().getExplicit()); EXPECT_EQ(2, schema.getFieldByName("bar").getProto().getOrdinal().getExplicit()); EXPECT_EQ(8, schema.getFieldByName("baz").getProto().getOrdinal().getExplicit()); EXPECT_EQ(0, schema.getFieldByName("qux").getProto().getOrdinal().getExplicit()); EXPECT_EQ(6, schema.getFieldByName("quux").getProto().getOrdinal().getExplicit()); EXPECT_EQ(4, schema.getFieldByName("corge").getProto().getOrdinal().getExplicit()); EXPECT_EQ(1, schema.getFieldByName("grault").getProto().getOrdinal().getExplicit()); EXPECT_EQ(7, schema.getFieldByName("garply").getProto().getOrdinal().getExplicit()); EXPECT_EQ(5, schema.getFieldByName("waldo").getProto().getOrdinal().getExplicit()); } TEST(Schema, Unions) { auto schema = Schema::from().asStruct(); EXPECT_TRUE(schema.findFieldByName("bit0") != nullptr); EXPECT_TRUE(schema.findFieldByName("u1f0s8") == nullptr); auto union1 = schema.getFieldByName("union1"); auto union1g = schema.getDependency(union1.getProto().getGroup().getTypeId()).asStruct(); EXPECT_EQ(schema, union1g.getDependency(union1g.getProto().getScopeId())); EXPECT_TRUE(union1g.findFieldByName("bin0") == nullptr); auto u1f0s8 = union1g.getFieldByName("u1f0s8"); EXPECT_EQ("u1f0s8", u1f0s8.getProto().getName()); EXPECT_TRUE(u1f0s8.getContainingStruct() == union1g); EXPECT_TRUE(union1g.findFieldByName("u1f1s8") != nullptr); EXPECT_TRUE(union1g.findFieldByName("u1f0s32") != nullptr); EXPECT_TRUE(union1g.findFieldByName("u1f0sp") != nullptr); EXPECT_TRUE(union1g.findFieldByName("u1f1s1") != nullptr); EXPECT_TRUE(union1g.findFieldByName("u0f0s1") == nullptr); EXPECT_TRUE(union1g.findFieldByName("u2f0s8") == nullptr); EXPECT_TRUE(union1g.findFieldByName("noSuchField") == nullptr); } TEST(Schema, Enums) { EnumSchema schema = Schema::from(); EXPECT_EQ(typeId(), schema.getProto().getId()); EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId())); EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId())); EXPECT_NONFATAL_FAILURE(schema.asStruct()); EXPECT_NONFATAL_FAILURE(schema.asInterface()); EXPECT_TRUE(schema.asEnum() == schema); ASSERT_EQ(schema.getEnumerants().size(), schema.getProto().getEnum().getEnumerants().size()); EnumSchema::Enumerant enumerant = schema.getEnumerants()[0]; EXPECT_EQ("foo", enumerant.getProto().getName()); EXPECT_TRUE(enumerant.getContainingEnum() == schema); EnumSchema::Enumerant lookup = schema.getEnumerantByName("foo"); EXPECT_TRUE(lookup == enumerant); EXPECT_TRUE(lookup != schema.getEnumerants()[1]); EXPECT_TRUE(schema.findEnumerantByName("noSuchEnumerant") == nullptr); EXPECT_TRUE(schema.findEnumerantByName("bar") != nullptr); EXPECT_TRUE(schema.findEnumerantByName("qux") != nullptr); EXPECT_TRUE(schema.findEnumerantByName("corge") != nullptr); EXPECT_TRUE(schema.findEnumerantByName("grault") != nullptr); } // TODO(someday): Test interface schemas when interfaces are implemented. TEST(Schema, Lists) { EXPECT_EQ(schema::Type::VOID, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::BOOL, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::INT8, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::INT16, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::INT32, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::INT64, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::UINT8, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::UINT16, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::UINT32, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::UINT64, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::FLOAT32, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::FLOAT64, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::TEXT, Schema::from>().whichElementType()); EXPECT_EQ(schema::Type::DATA, Schema::from>().whichElementType()); EXPECT_NONFATAL_FAILURE(Schema::from>().getStructElementType()); EXPECT_NONFATAL_FAILURE(Schema::from>().getEnumElementType()); EXPECT_NONFATAL_FAILURE(Schema::from>().getInterfaceElementType()); EXPECT_NONFATAL_FAILURE(Schema::from>().getListElementType()); { ListSchema schema = Schema::from>(); EXPECT_EQ(schema::Type::STRUCT, schema.whichElementType()); EXPECT_TRUE(schema.getStructElementType() == Schema::from()); EXPECT_NONFATAL_FAILURE(schema.getEnumElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); EXPECT_NONFATAL_FAILURE(schema.getListElementType()); } { ListSchema schema = Schema::from>(); EXPECT_EQ(schema::Type::ENUM, schema.whichElementType()); EXPECT_TRUE(schema.getEnumElementType() == Schema::from()); EXPECT_NONFATAL_FAILURE(schema.getStructElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); EXPECT_NONFATAL_FAILURE(schema.getListElementType()); } // TODO(someday): Test interfaces. { ListSchema schema = Schema::from>>(); EXPECT_EQ(schema::Type::LIST, schema.whichElementType()); EXPECT_NONFATAL_FAILURE(schema.getStructElementType()); EXPECT_NONFATAL_FAILURE(schema.getEnumElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); ListSchema inner = schema.getListElementType(); EXPECT_EQ(schema::Type::INT32, inner.whichElementType()); } { ListSchema schema = Schema::from>>(); EXPECT_EQ(schema::Type::LIST, schema.whichElementType()); EXPECT_NONFATAL_FAILURE(schema.getStructElementType()); EXPECT_NONFATAL_FAILURE(schema.getEnumElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); ListSchema inner = schema.getListElementType(); EXPECT_EQ(schema::Type::STRUCT, inner.whichElementType()); EXPECT_TRUE(inner.getStructElementType() == Schema::from()); } { ListSchema schema = Schema::from>>(); EXPECT_EQ(schema::Type::LIST, schema.whichElementType()); EXPECT_NONFATAL_FAILURE(schema.getStructElementType()); EXPECT_NONFATAL_FAILURE(schema.getEnumElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); ListSchema inner = schema.getListElementType(); EXPECT_EQ(schema::Type::ENUM, inner.whichElementType()); EXPECT_TRUE(inner.getEnumElementType() == Schema::from()); } { auto context = Schema::from(); auto type = context.getFieldByName("enumList").getProto().getSlot().getType(); ListSchema schema = ListSchema::of(type.getList().getElementType(), context); EXPECT_EQ(schema::Type::ENUM, schema.whichElementType()); EXPECT_TRUE(schema.getEnumElementType() == Schema::from()); EXPECT_NONFATAL_FAILURE(schema.getStructElementType()); EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType()); EXPECT_NONFATAL_FAILURE(schema.getListElementType()); } } TEST(Schema, UnnamedUnion) { StructSchema schema = Schema::from(); EXPECT_TRUE(schema.findFieldByName("") == nullptr); EXPECT_TRUE(schema.findFieldByName("foo") != nullptr); EXPECT_TRUE(schema.findFieldByName("bar") != nullptr); EXPECT_TRUE(schema.findFieldByName("before") != nullptr); EXPECT_TRUE(schema.findFieldByName("after") != nullptr); } TEST(Schema, NullSchemas) { EXPECT_EQ(0xff, (uint)Schema().getProto().which()); EXPECT_TRUE(StructSchema().getProto().isStruct()); EXPECT_TRUE(EnumSchema().getProto().isEnum()); EXPECT_TRUE(InterfaceSchema().getProto().isInterface()); EXPECT_TRUE(ConstSchema().getProto().isConst()); EXPECT_EQ("(null schema)", Schema().getProto().getDisplayName()); EXPECT_EQ("(null struct schema)", StructSchema().getProto().getDisplayName()); EXPECT_EQ("(null enum schema)", EnumSchema().getProto().getDisplayName()); EXPECT_EQ("(null interface schema)", InterfaceSchema().getProto().getDisplayName()); EXPECT_EQ("(null const schema)", ConstSchema().getProto().getDisplayName()); EXPECT_TRUE(Schema::from() == InterfaceSchema()); EXPECT_EQ(InterfaceSchema().getProto().getId(), typeId()); } TEST(Schema, Interfaces) { InterfaceSchema schema = Schema::from(); EXPECT_EQ(typeId(), schema.getProto().getId()); EXPECT_TRUE(schema.getDependency(typeId()) == Schema::from()); EXPECT_TRUE(schema.getDependency(typeId()) != schema); EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId())); EXPECT_TRUE(schema.asInterface() == schema); EXPECT_NONFATAL_FAILURE(schema.asStruct()); EXPECT_NONFATAL_FAILURE(schema.asEnum()); ASSERT_EQ(schema.getMethods().size(), schema.getProto().getInterface().getMethods().size()); InterfaceSchema::Method method = schema.getMethods()[0]; EXPECT_EQ("callFoo", method.getProto().getName()); EXPECT_TRUE(method.getContainingInterface() == schema); InterfaceSchema::Method lookup = schema.getMethodByName("callFoo"); EXPECT_TRUE(lookup == method); EXPECT_TRUE(lookup != schema.getMethods()[1]); EXPECT_TRUE(Schema::from().getFieldByName("int32Field") .getProto().getSlot().getHadExplicitDefault()); EXPECT_TRUE(schema.findMethodByName("noSuchMethod") == nullptr); EXPECT_TRUE(schema.findMethodByName("callFooWhenResolved") != nullptr); EXPECT_TRUE(schema.findMethodByName("neverReturn") != nullptr); EXPECT_TRUE(schema.findMethodByName("hold") != nullptr); EXPECT_TRUE(schema.findMethodByName("callHeld") != nullptr); EXPECT_TRUE(schema.findMethodByName("getHeld") != nullptr); auto params = schema.getDependency(schema.getMethodByName("methodWithDefaults") .getProto().getParamStructType()).asStruct(); EXPECT_FALSE(params.getFieldByName("a").getProto().getSlot().getHadExplicitDefault()); EXPECT_TRUE(params.getFieldByName("b").getProto().getSlot().getHadExplicitDefault()); EXPECT_TRUE(params.getFieldByName("c").getProto().getSlot().getHadExplicitDefault()); } TEST(Schema, Generics) { StructSchema allTypes = Schema::from(); StructSchema tap = Schema::from(); StructSchema schema = Schema::from(); StructSchema branded; { StructSchema::Field basic = schema.getFieldByName("basic"); branded = basic.getType().asStruct(); StructSchema::Field foo = branded.getFieldByName("foo"); EXPECT_TRUE(foo.getType().asStruct() == allTypes); EXPECT_TRUE(foo.getType().asStruct() != tap); StructSchema instance2 = branded.getFieldByName("rev").getType().asStruct(); StructSchema::Field foo2 = instance2.getFieldByName("foo"); EXPECT_TRUE(foo2.getType().asStruct() == tap); EXPECT_TRUE(foo2.getType().asStruct() != allTypes); } { StructSchema inner2 = schema.getFieldByName("inner2").getType().asStruct(); StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct(); Type boundFoo = bound.getFieldByName("foo").getType(); EXPECT_FALSE(boundFoo.isAnyPointer()); EXPECT_TRUE(boundFoo.asStruct() == allTypes); StructSchema unbound = inner2.getFieldByName("innerUnbound").getType().asStruct(); Type unboundFoo = unbound.getFieldByName("foo").getType(); EXPECT_TRUE(unboundFoo.isAnyPointer()); } { InterfaceSchema cap = schema.getFieldByName("genericCap").getType().asInterface(); InterfaceSchema::Method method = cap.getMethodByName("call"); StructSchema inner2 = method.getParamType(); StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct(); Type boundFoo = bound.getFieldByName("foo").getType(); EXPECT_FALSE(boundFoo.isAnyPointer()); EXPECT_TRUE(boundFoo.asStruct() == allTypes); EXPECT_TRUE(inner2.getFieldByName("baz").getType().isText()); StructSchema results = method.getResultType(); EXPECT_TRUE(results.getFieldByName("qux").getType().isData()); EXPECT_TRUE(results.getFieldByName("gen").getType().asStruct() == branded); } } KJ_TEST("StructSchema::hasNoCapabilites()") { // At present, TestAllTypes doesn't actually cover interfaces or AnyPointer. KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(Schema::from().mayContainCapabilities()); KJ_EXPECT(Schema::from().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); // Generic arguments could be capabilities. KJ_EXPECT(Schema::from::Inner>().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(!Schema::from().mayContainCapabilities()); KJ_EXPECT(Schema::from().mayContainCapabilities()); KJ_EXPECT(Schema::from().mayContainCapabilities()); } KJ_TEST("list-of-enum as generic type parameter has working schema") { // Tests for a bug where when a list-of-enum type was used as a type parameter to a generic, // the schema would be constructed wrong. auto field = Schema::from() .getFieldByName("bindEnumList").getType().asStruct() .getFieldByName("foo"); auto type = field.getType(); KJ_ASSERT(type.isList()); auto elementType = type.asList().getElementType(); KJ_ASSERT(elementType.isEnum()); KJ_ASSERT(elementType.asEnum() == Schema::from()); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema.capnp.h0000644000175000017500000124126514731562162021365 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: schema.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(e682ab4cf923a417); CAPNP_DECLARE_SCHEMA(b9521bccf10fa3b1); CAPNP_DECLARE_SCHEMA(debf55bbfa0fc242); CAPNP_DECLARE_SCHEMA(f38e1de3041357ae); CAPNP_DECLARE_SCHEMA(c2ba9038898e1fa2); CAPNP_DECLARE_SCHEMA(9ea0b19b37fb4435); CAPNP_DECLARE_SCHEMA(b54ab3364333f598); CAPNP_DECLARE_SCHEMA(e82753cff0c2218f); CAPNP_DECLARE_SCHEMA(b18aa5ac7a0d9420); CAPNP_DECLARE_SCHEMA(ec1619d4400a0290); CAPNP_DECLARE_SCHEMA(9aad50a41f4af45f); CAPNP_DECLARE_SCHEMA(97b14cbe7cfec712); CAPNP_DECLARE_SCHEMA(c42305476bb4746f); CAPNP_DECLARE_SCHEMA(cafccddb68db1d11); CAPNP_DECLARE_SCHEMA(bb90d5c287870be6); CAPNP_DECLARE_SCHEMA(978a7cebdc549a4d); CAPNP_DECLARE_SCHEMA(a9962a9ed0a4d7f8); CAPNP_DECLARE_SCHEMA(9500cce23b334d80); CAPNP_DECLARE_SCHEMA(d07378ede1f9cc60); CAPNP_DECLARE_SCHEMA(87e739250a60ea97); CAPNP_DECLARE_SCHEMA(9e0e78711a7f87a9); CAPNP_DECLARE_SCHEMA(ac3a6f60ef4cc6d3); CAPNP_DECLARE_SCHEMA(ed8bca69f7fb0cbf); CAPNP_DECLARE_SCHEMA(c2573fe8a23e49f1); CAPNP_DECLARE_SCHEMA(8e3b5f79fe593656); CAPNP_DECLARE_SCHEMA(9dd1f724f4614a85); CAPNP_DECLARE_SCHEMA(baefc9120c56e274); CAPNP_DECLARE_SCHEMA(903455f06065422b); CAPNP_DECLARE_SCHEMA(abd73485a9636bc9); CAPNP_DECLARE_SCHEMA(c863cd16969ee7fc); CAPNP_DECLARE_SCHEMA(ce23dcd2d7b00c9b); CAPNP_DECLARE_SCHEMA(f1c8950dab257542); CAPNP_DECLARE_SCHEMA(d1958f7dba521926); enum class ElementSize_d1958f7dba521926: uint16_t { EMPTY, BIT, BYTE, TWO_BYTES, FOUR_BYTES, EIGHT_BYTES, POINTER, INLINE_COMPOSITE, }; CAPNP_DECLARE_ENUM(ElementSize, d1958f7dba521926); CAPNP_DECLARE_SCHEMA(d85d305b7d839963); CAPNP_DECLARE_SCHEMA(bfc546f6210ad7ce); CAPNP_DECLARE_SCHEMA(cfea0eb02e810062); CAPNP_DECLARE_SCHEMA(ae504193122357e5); CAPNP_DECLARE_SCHEMA(f8ea2bf176925da0); CAPNP_DECLARE_SCHEMA(dda719892e0499bb); CAPNP_DECLARE_SCHEMA(fc69d5e1d630a151); } // namespace schemas } // namespace capnp namespace capnp { namespace schema { struct Node { Node() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { FILE, STRUCT, ENUM, INTERFACE, CONST, ANNOTATION, }; struct Parameter; struct NestedNode; struct SourceInfo; struct Struct; struct Enum; struct Interface; struct Const; struct Annotation; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e682ab4cf923a417, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Parameter { Parameter() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b9521bccf10fa3b1, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::NestedNode { NestedNode() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(debf55bbfa0fc242, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::SourceInfo { SourceInfo() = delete; class Reader; class Builder; class Pipeline; struct Member; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f38e1de3041357ae, 2, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::SourceInfo::Member { Member() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c2ba9038898e1fa2, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Struct { Struct() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9ea0b19b37fb4435, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Enum { Enum() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b54ab3364333f598, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Interface { Interface() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e82753cff0c2218f, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Const { Const() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b18aa5ac7a0d9420, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Node::Annotation { Annotation() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ec1619d4400a0290, 6, 6) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Field { Field() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { SLOT, GROUP, }; static constexpr ::uint16_t NO_DISCRIMINANT = 65535u; struct Slot; struct Group; struct Ordinal; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9aad50a41f4af45f, 3, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Field::Slot { Slot() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c42305476bb4746f, 3, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Field::Group { Group() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(cafccddb68db1d11, 3, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Field::Ordinal { Ordinal() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { IMPLICIT, EXPLICIT, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(bb90d5c287870be6, 3, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Enumerant { Enumerant() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(978a7cebdc549a4d, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Superclass { Superclass() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(a9962a9ed0a4d7f8, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Method { Method() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9500cce23b334d80, 3, 5) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type { Type() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { VOID, BOOL, INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64, FLOAT32, FLOAT64, TEXT, DATA, LIST, ENUM, STRUCT, INTERFACE, ANY_POINTER, }; struct List; struct Enum; struct Struct; struct Interface; struct AnyPointer; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d07378ede1f9cc60, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::List { List() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(87e739250a60ea97, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::Enum { Enum() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9e0e78711a7f87a9, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::Struct { Struct() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ac3a6f60ef4cc6d3, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::Interface { Interface() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ed8bca69f7fb0cbf, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::AnyPointer { AnyPointer() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNCONSTRAINED, PARAMETER, IMPLICIT_METHOD_PARAMETER, }; struct Unconstrained; struct Parameter; struct ImplicitMethodParameter; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c2573fe8a23e49f1, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::AnyPointer::Unconstrained { Unconstrained() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { ANY_KIND, STRUCT, LIST, CAPABILITY, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(8e3b5f79fe593656, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::AnyPointer::Parameter { Parameter() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9dd1f724f4614a85, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Type::AnyPointer::ImplicitMethodParameter { ImplicitMethodParameter() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(baefc9120c56e274, 3, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Brand { Brand() = delete; class Reader; class Builder; class Pipeline; struct Scope; struct Binding; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(903455f06065422b, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Brand::Scope { Scope() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { BIND, INHERIT, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(abd73485a9636bc9, 2, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Brand::Binding { Binding() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNBOUND, TYPE, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c863cd16969ee7fc, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Value { Value() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { VOID, BOOL, INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64, FLOAT32, FLOAT64, TEXT, DATA, LIST, ENUM, STRUCT, INTERFACE, ANY_POINTER, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ce23dcd2d7b00c9b, 2, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Annotation { Annotation() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f1c8950dab257542, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; typedef ::capnp::schemas::ElementSize_d1958f7dba521926 ElementSize; struct CapnpVersion { CapnpVersion() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d85d305b7d839963, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest { CodeGeneratorRequest() = delete; class Reader; class Builder; class Pipeline; struct RequestedFile; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(bfc546f6210ad7ce, 0, 4) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest::RequestedFile { RequestedFile() = delete; class Reader; class Builder; class Pipeline; struct Import; struct FileSourceInfo; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(cfea0eb02e810062, 1, 3) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest::RequestedFile::Import { Import() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ae504193122357e5, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest::RequestedFile::FileSourceInfo { FileSourceInfo() = delete; class Reader; class Builder; class Pipeline; struct Identifier; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f8ea2bf176925da0, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier { Identifier() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { TYPE_ID, MEMBER, }; struct Member; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(dda719892e0499bb, 3, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member { Member() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(fc69d5e1d630a151, 3, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class Node::Reader { public: typedef Node Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline ::uint64_t getId() const; inline bool hasDisplayName() const; inline ::capnp::Text::Reader getDisplayName() const; inline ::uint32_t getDisplayNamePrefixLength() const; inline ::uint64_t getScopeId() const; inline bool hasNestedNodes() const; inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader getNestedNodes() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; inline bool isFile() const; inline ::capnp::Void getFile() const; inline bool isStruct() const; inline typename Struct::Reader getStruct() const; inline bool isEnum() const; inline typename Enum::Reader getEnum() const; inline bool isInterface() const; inline typename Interface::Reader getInterface() const; inline bool isConst() const; inline typename Const::Reader getConst() const; inline bool isAnnotation() const; inline typename Annotation::Reader getAnnotation() const; inline bool hasParameters() const; inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader getParameters() const; inline bool getIsGeneric() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Builder { public: typedef Node Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasDisplayName(); inline ::capnp::Text::Builder getDisplayName(); inline void setDisplayName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initDisplayName(unsigned int size); inline void adoptDisplayName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownDisplayName(); inline ::uint32_t getDisplayNamePrefixLength(); inline void setDisplayNamePrefixLength( ::uint32_t value); inline ::uint64_t getScopeId(); inline void setScopeId( ::uint64_t value); inline bool hasNestedNodes(); inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder getNestedNodes(); inline void setNestedNodes( ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder initNestedNodes(unsigned int size); inline void adoptNestedNodes(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>> disownNestedNodes(); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); inline bool isFile(); inline ::capnp::Void getFile(); inline void setFile( ::capnp::Void value = ::capnp::VOID); inline bool isStruct(); inline typename Struct::Builder getStruct(); inline typename Struct::Builder initStruct(); inline bool isEnum(); inline typename Enum::Builder getEnum(); inline typename Enum::Builder initEnum(); inline bool isInterface(); inline typename Interface::Builder getInterface(); inline typename Interface::Builder initInterface(); inline bool isConst(); inline typename Const::Builder getConst(); inline typename Const::Builder initConst(); inline bool isAnnotation(); inline typename Annotation::Builder getAnnotation(); inline typename Annotation::Builder initAnnotation(); inline bool hasParameters(); inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder getParameters(); inline void setParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder initParameters(unsigned int size); inline void adoptParameters(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> disownParameters(); inline bool getIsGeneric(); inline void setIsGeneric(bool value); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Pipeline { public: typedef Node Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Parameter::Reader { public: typedef Parameter Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Parameter::Builder { public: typedef Parameter Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Parameter::Pipeline { public: typedef Parameter Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::NestedNode::Reader { public: typedef NestedNode Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline ::uint64_t getId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::NestedNode::Builder { public: typedef NestedNode Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline ::uint64_t getId(); inline void setId( ::uint64_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::NestedNode::Pipeline { public: typedef NestedNode Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::SourceInfo::Reader { public: typedef SourceInfo Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getId() const; inline bool hasDocComment() const; inline ::capnp::Text::Reader getDocComment() const; inline bool hasMembers() const; inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Reader getMembers() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::SourceInfo::Builder { public: typedef SourceInfo Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasDocComment(); inline ::capnp::Text::Builder getDocComment(); inline void setDocComment( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initDocComment(unsigned int size); inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); inline bool hasMembers(); inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Builder getMembers(); inline void setMembers( ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Builder initMembers(unsigned int size); inline void adoptMembers(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>> disownMembers(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::SourceInfo::Pipeline { public: typedef SourceInfo Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::SourceInfo::Member::Reader { public: typedef Member Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasDocComment() const; inline ::capnp::Text::Reader getDocComment() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool hasTypeId() const; inline ::capnp::Text::Reader getTypeId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::SourceInfo::Member::Builder { public: typedef Member Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasDocComment(); inline ::capnp::Text::Builder getDocComment(); inline void setDocComment( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initDocComment(unsigned int size); inline void adoptDocComment(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownDocComment(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool hasTypeId(); inline ::capnp::Text::Builder getTypeId(); inline void setTypeId( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initTypeId(unsigned int size); inline void adoptTypeId(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownTypeId(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::SourceInfo::Member::Pipeline { public: typedef Member Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Struct::Reader { public: typedef Struct Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint16_t getDataWordCount() const; inline ::uint16_t getPointerCount() const; inline ::capnp::schema::ElementSize getPreferredListEncoding() const; inline bool getIsGroup() const; inline ::uint16_t getDiscriminantCount() const; inline ::uint32_t getDiscriminantOffset() const; inline bool hasFields() const; inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader getFields() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Struct::Builder { public: typedef Struct Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint16_t getDataWordCount(); inline void setDataWordCount( ::uint16_t value); inline ::uint16_t getPointerCount(); inline void setPointerCount( ::uint16_t value); inline ::capnp::schema::ElementSize getPreferredListEncoding(); inline void setPreferredListEncoding( ::capnp::schema::ElementSize value); inline bool getIsGroup(); inline void setIsGroup(bool value); inline ::uint16_t getDiscriminantCount(); inline void setDiscriminantCount( ::uint16_t value); inline ::uint32_t getDiscriminantOffset(); inline void setDiscriminantOffset( ::uint32_t value); inline bool hasFields(); inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder getFields(); inline void setFields( ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder initFields(unsigned int size); inline void adoptFields(::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>> disownFields(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Struct::Pipeline { public: typedef Struct Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Enum::Reader { public: typedef Enum Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasEnumerants() const; inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader getEnumerants() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Enum::Builder { public: typedef Enum Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasEnumerants(); inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder getEnumerants(); inline void setEnumerants( ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder initEnumerants(unsigned int size); inline void adoptEnumerants(::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>> disownEnumerants(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Enum::Pipeline { public: typedef Enum Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Interface::Reader { public: typedef Interface Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasMethods() const; inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader getMethods() const; inline bool hasSuperclasses() const; inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader getSuperclasses() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Interface::Builder { public: typedef Interface Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasMethods(); inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder getMethods(); inline void setMethods( ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder initMethods(unsigned int size); inline void adoptMethods(::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>> disownMethods(); inline bool hasSuperclasses(); inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder getSuperclasses(); inline void setSuperclasses( ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder initSuperclasses(unsigned int size); inline void adoptSuperclasses(::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>> disownSuperclasses(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Interface::Pipeline { public: typedef Interface Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Const::Reader { public: typedef Const Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasType() const; inline ::capnp::schema::Type::Reader getType() const; inline bool hasValue() const; inline ::capnp::schema::Value::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Const::Builder { public: typedef Const Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasType(); inline ::capnp::schema::Type::Builder getType(); inline void setType( ::capnp::schema::Type::Reader value); inline ::capnp::schema::Type::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); inline bool hasValue(); inline ::capnp::schema::Value::Builder getValue(); inline void setValue( ::capnp::schema::Value::Reader value); inline ::capnp::schema::Value::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::schema::Value>&& value); inline ::capnp::Orphan< ::capnp::schema::Value> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Const::Pipeline { public: typedef Const Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Type::Pipeline getType(); inline ::capnp::schema::Value::Pipeline getValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Node::Annotation::Reader { public: typedef Annotation Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasType() const; inline ::capnp::schema::Type::Reader getType() const; inline bool getTargetsFile() const; inline bool getTargetsConst() const; inline bool getTargetsEnum() const; inline bool getTargetsEnumerant() const; inline bool getTargetsStruct() const; inline bool getTargetsField() const; inline bool getTargetsUnion() const; inline bool getTargetsGroup() const; inline bool getTargetsInterface() const; inline bool getTargetsMethod() const; inline bool getTargetsParam() const; inline bool getTargetsAnnotation() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Node::Annotation::Builder { public: typedef Annotation Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasType(); inline ::capnp::schema::Type::Builder getType(); inline void setType( ::capnp::schema::Type::Reader value); inline ::capnp::schema::Type::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); inline bool getTargetsFile(); inline void setTargetsFile(bool value); inline bool getTargetsConst(); inline void setTargetsConst(bool value); inline bool getTargetsEnum(); inline void setTargetsEnum(bool value); inline bool getTargetsEnumerant(); inline void setTargetsEnumerant(bool value); inline bool getTargetsStruct(); inline void setTargetsStruct(bool value); inline bool getTargetsField(); inline void setTargetsField(bool value); inline bool getTargetsUnion(); inline void setTargetsUnion(bool value); inline bool getTargetsGroup(); inline void setTargetsGroup(bool value); inline bool getTargetsInterface(); inline void setTargetsInterface(bool value); inline bool getTargetsMethod(); inline void setTargetsMethod(bool value); inline bool getTargetsParam(); inline void setTargetsParam(bool value); inline bool getTargetsAnnotation(); inline void setTargetsAnnotation(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Node::Annotation::Pipeline { public: typedef Annotation Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Type::Pipeline getType(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Field::Reader { public: typedef Field Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline ::uint16_t getCodeOrder() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; inline ::uint16_t getDiscriminantValue() const; inline bool isSlot() const; inline typename Slot::Reader getSlot() const; inline bool isGroup() const; inline typename Group::Reader getGroup() const; inline typename Ordinal::Reader getOrdinal() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Field::Builder { public: typedef Field Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline ::uint16_t getCodeOrder(); inline void setCodeOrder( ::uint16_t value); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); inline ::uint16_t getDiscriminantValue(); inline void setDiscriminantValue( ::uint16_t value); inline bool isSlot(); inline typename Slot::Builder getSlot(); inline typename Slot::Builder initSlot(); inline bool isGroup(); inline typename Group::Builder getGroup(); inline typename Group::Builder initGroup(); inline typename Ordinal::Builder getOrdinal(); inline typename Ordinal::Builder initOrdinal(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Field::Pipeline { public: typedef Field Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline typename Ordinal::Pipeline getOrdinal(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Field::Slot::Reader { public: typedef Slot Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getOffset() const; inline bool hasType() const; inline ::capnp::schema::Type::Reader getType() const; inline bool hasDefaultValue() const; inline ::capnp::schema::Value::Reader getDefaultValue() const; inline bool getHadExplicitDefault() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Field::Slot::Builder { public: typedef Slot Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getOffset(); inline void setOffset( ::uint32_t value); inline bool hasType(); inline ::capnp::schema::Type::Builder getType(); inline void setType( ::capnp::schema::Type::Reader value); inline ::capnp::schema::Type::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); inline bool hasDefaultValue(); inline ::capnp::schema::Value::Builder getDefaultValue(); inline void setDefaultValue( ::capnp::schema::Value::Reader value); inline ::capnp::schema::Value::Builder initDefaultValue(); inline void adoptDefaultValue(::capnp::Orphan< ::capnp::schema::Value>&& value); inline ::capnp::Orphan< ::capnp::schema::Value> disownDefaultValue(); inline bool getHadExplicitDefault(); inline void setHadExplicitDefault(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Field::Slot::Pipeline { public: typedef Slot Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Type::Pipeline getType(); inline ::capnp::schema::Value::Pipeline getDefaultValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Field::Group::Reader { public: typedef Group Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Field::Group::Builder { public: typedef Group Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId(); inline void setTypeId( ::uint64_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Field::Group::Pipeline { public: typedef Group Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Field::Ordinal::Reader { public: typedef Ordinal Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isImplicit() const; inline ::capnp::Void getImplicit() const; inline bool isExplicit() const; inline ::uint16_t getExplicit() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Field::Ordinal::Builder { public: typedef Ordinal Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isImplicit(); inline ::capnp::Void getImplicit(); inline void setImplicit( ::capnp::Void value = ::capnp::VOID); inline bool isExplicit(); inline ::uint16_t getExplicit(); inline void setExplicit( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Field::Ordinal::Pipeline { public: typedef Ordinal Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Enumerant::Reader { public: typedef Enumerant Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline ::uint16_t getCodeOrder() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Enumerant::Builder { public: typedef Enumerant Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline ::uint16_t getCodeOrder(); inline void setCodeOrder( ::uint16_t value); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Enumerant::Pipeline { public: typedef Enumerant Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Superclass::Reader { public: typedef Superclass Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getId() const; inline bool hasBrand() const; inline ::capnp::schema::Brand::Reader getBrand() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Superclass::Builder { public: typedef Superclass Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasBrand(); inline ::capnp::schema::Brand::Builder getBrand(); inline void setBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initBrand(); inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Superclass::Pipeline { public: typedef Superclass Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Brand::Pipeline getBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Method::Reader { public: typedef Method Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline ::uint16_t getCodeOrder() const; inline ::uint64_t getParamStructType() const; inline ::uint64_t getResultStructType() const; inline bool hasAnnotations() const; inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader getAnnotations() const; inline bool hasParamBrand() const; inline ::capnp::schema::Brand::Reader getParamBrand() const; inline bool hasResultBrand() const; inline ::capnp::schema::Brand::Reader getResultBrand() const; inline bool hasImplicitParameters() const; inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader getImplicitParameters() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Method::Builder { public: typedef Method Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline ::uint16_t getCodeOrder(); inline void setCodeOrder( ::uint16_t value); inline ::uint64_t getParamStructType(); inline void setParamStructType( ::uint64_t value); inline ::uint64_t getResultStructType(); inline void setResultStructType( ::uint64_t value); inline bool hasAnnotations(); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder getAnnotations(); inline void setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder initAnnotations(unsigned int size); inline void adoptAnnotations(::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> disownAnnotations(); inline bool hasParamBrand(); inline ::capnp::schema::Brand::Builder getParamBrand(); inline void setParamBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initParamBrand(); inline void adoptParamBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownParamBrand(); inline bool hasResultBrand(); inline ::capnp::schema::Brand::Builder getResultBrand(); inline void setResultBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initResultBrand(); inline void adoptResultBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownResultBrand(); inline bool hasImplicitParameters(); inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder getImplicitParameters(); inline void setImplicitParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder initImplicitParameters(unsigned int size); inline void adoptImplicitParameters(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> disownImplicitParameters(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Method::Pipeline { public: typedef Method Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Brand::Pipeline getParamBrand(); inline ::capnp::schema::Brand::Pipeline getResultBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::Reader { public: typedef Type Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isVoid() const; inline ::capnp::Void getVoid() const; inline bool isBool() const; inline ::capnp::Void getBool() const; inline bool isInt8() const; inline ::capnp::Void getInt8() const; inline bool isInt16() const; inline ::capnp::Void getInt16() const; inline bool isInt32() const; inline ::capnp::Void getInt32() const; inline bool isInt64() const; inline ::capnp::Void getInt64() const; inline bool isUint8() const; inline ::capnp::Void getUint8() const; inline bool isUint16() const; inline ::capnp::Void getUint16() const; inline bool isUint32() const; inline ::capnp::Void getUint32() const; inline bool isUint64() const; inline ::capnp::Void getUint64() const; inline bool isFloat32() const; inline ::capnp::Void getFloat32() const; inline bool isFloat64() const; inline ::capnp::Void getFloat64() const; inline bool isText() const; inline ::capnp::Void getText() const; inline bool isData() const; inline ::capnp::Void getData() const; inline bool isList() const; inline typename List::Reader getList() const; inline bool isEnum() const; inline typename Enum::Reader getEnum() const; inline bool isStruct() const; inline typename Struct::Reader getStruct() const; inline bool isInterface() const; inline typename Interface::Reader getInterface() const; inline bool isAnyPointer() const; inline typename AnyPointer::Reader getAnyPointer() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::Builder { public: typedef Type Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isVoid(); inline ::capnp::Void getVoid(); inline void setVoid( ::capnp::Void value = ::capnp::VOID); inline bool isBool(); inline ::capnp::Void getBool(); inline void setBool( ::capnp::Void value = ::capnp::VOID); inline bool isInt8(); inline ::capnp::Void getInt8(); inline void setInt8( ::capnp::Void value = ::capnp::VOID); inline bool isInt16(); inline ::capnp::Void getInt16(); inline void setInt16( ::capnp::Void value = ::capnp::VOID); inline bool isInt32(); inline ::capnp::Void getInt32(); inline void setInt32( ::capnp::Void value = ::capnp::VOID); inline bool isInt64(); inline ::capnp::Void getInt64(); inline void setInt64( ::capnp::Void value = ::capnp::VOID); inline bool isUint8(); inline ::capnp::Void getUint8(); inline void setUint8( ::capnp::Void value = ::capnp::VOID); inline bool isUint16(); inline ::capnp::Void getUint16(); inline void setUint16( ::capnp::Void value = ::capnp::VOID); inline bool isUint32(); inline ::capnp::Void getUint32(); inline void setUint32( ::capnp::Void value = ::capnp::VOID); inline bool isUint64(); inline ::capnp::Void getUint64(); inline void setUint64( ::capnp::Void value = ::capnp::VOID); inline bool isFloat32(); inline ::capnp::Void getFloat32(); inline void setFloat32( ::capnp::Void value = ::capnp::VOID); inline bool isFloat64(); inline ::capnp::Void getFloat64(); inline void setFloat64( ::capnp::Void value = ::capnp::VOID); inline bool isText(); inline ::capnp::Void getText(); inline void setText( ::capnp::Void value = ::capnp::VOID); inline bool isData(); inline ::capnp::Void getData(); inline void setData( ::capnp::Void value = ::capnp::VOID); inline bool isList(); inline typename List::Builder getList(); inline typename List::Builder initList(); inline bool isEnum(); inline typename Enum::Builder getEnum(); inline typename Enum::Builder initEnum(); inline bool isStruct(); inline typename Struct::Builder getStruct(); inline typename Struct::Builder initStruct(); inline bool isInterface(); inline typename Interface::Builder getInterface(); inline typename Interface::Builder initInterface(); inline bool isAnyPointer(); inline typename AnyPointer::Builder getAnyPointer(); inline typename AnyPointer::Builder initAnyPointer(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::Pipeline { public: typedef Type Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::List::Reader { public: typedef List Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasElementType() const; inline ::capnp::schema::Type::Reader getElementType() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::List::Builder { public: typedef List Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasElementType(); inline ::capnp::schema::Type::Builder getElementType(); inline void setElementType( ::capnp::schema::Type::Reader value); inline ::capnp::schema::Type::Builder initElementType(); inline void adoptElementType(::capnp::Orphan< ::capnp::schema::Type>&& value); inline ::capnp::Orphan< ::capnp::schema::Type> disownElementType(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::List::Pipeline { public: typedef List Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Type::Pipeline getElementType(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::Enum::Reader { public: typedef Enum Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId() const; inline bool hasBrand() const; inline ::capnp::schema::Brand::Reader getBrand() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::Enum::Builder { public: typedef Enum Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId(); inline void setTypeId( ::uint64_t value); inline bool hasBrand(); inline ::capnp::schema::Brand::Builder getBrand(); inline void setBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initBrand(); inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::Enum::Pipeline { public: typedef Enum Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Brand::Pipeline getBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::Struct::Reader { public: typedef Struct Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId() const; inline bool hasBrand() const; inline ::capnp::schema::Brand::Reader getBrand() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::Struct::Builder { public: typedef Struct Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId(); inline void setTypeId( ::uint64_t value); inline bool hasBrand(); inline ::capnp::schema::Brand::Builder getBrand(); inline void setBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initBrand(); inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::Struct::Pipeline { public: typedef Struct Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Brand::Pipeline getBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::Interface::Reader { public: typedef Interface Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId() const; inline bool hasBrand() const; inline ::capnp::schema::Brand::Reader getBrand() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::Interface::Builder { public: typedef Interface Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getTypeId(); inline void setTypeId( ::uint64_t value); inline bool hasBrand(); inline ::capnp::schema::Brand::Builder getBrand(); inline void setBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initBrand(); inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::Interface::Pipeline { public: typedef Interface Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Brand::Pipeline getBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::AnyPointer::Reader { public: typedef AnyPointer Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnconstrained() const; inline typename Unconstrained::Reader getUnconstrained() const; inline bool isParameter() const; inline typename Parameter::Reader getParameter() const; inline bool isImplicitMethodParameter() const; inline typename ImplicitMethodParameter::Reader getImplicitMethodParameter() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::AnyPointer::Builder { public: typedef AnyPointer Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnconstrained(); inline typename Unconstrained::Builder getUnconstrained(); inline typename Unconstrained::Builder initUnconstrained(); inline bool isParameter(); inline typename Parameter::Builder getParameter(); inline typename Parameter::Builder initParameter(); inline bool isImplicitMethodParameter(); inline typename ImplicitMethodParameter::Builder getImplicitMethodParameter(); inline typename ImplicitMethodParameter::Builder initImplicitMethodParameter(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::AnyPointer::Pipeline { public: typedef AnyPointer Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::AnyPointer::Unconstrained::Reader { public: typedef Unconstrained Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isAnyKind() const; inline ::capnp::Void getAnyKind() const; inline bool isStruct() const; inline ::capnp::Void getStruct() const; inline bool isList() const; inline ::capnp::Void getList() const; inline bool isCapability() const; inline ::capnp::Void getCapability() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::AnyPointer::Unconstrained::Builder { public: typedef Unconstrained Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isAnyKind(); inline ::capnp::Void getAnyKind(); inline void setAnyKind( ::capnp::Void value = ::capnp::VOID); inline bool isStruct(); inline ::capnp::Void getStruct(); inline void setStruct( ::capnp::Void value = ::capnp::VOID); inline bool isList(); inline ::capnp::Void getList(); inline void setList( ::capnp::Void value = ::capnp::VOID); inline bool isCapability(); inline ::capnp::Void getCapability(); inline void setCapability( ::capnp::Void value = ::capnp::VOID); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::AnyPointer::Unconstrained::Pipeline { public: typedef Unconstrained Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::AnyPointer::Parameter::Reader { public: typedef Parameter Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getScopeId() const; inline ::uint16_t getParameterIndex() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::AnyPointer::Parameter::Builder { public: typedef Parameter Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getScopeId(); inline void setScopeId( ::uint64_t value); inline ::uint16_t getParameterIndex(); inline void setParameterIndex( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::AnyPointer::Parameter::Pipeline { public: typedef Parameter Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Type::AnyPointer::ImplicitMethodParameter::Reader { public: typedef ImplicitMethodParameter Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint16_t getParameterIndex() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Type::AnyPointer::ImplicitMethodParameter::Builder { public: typedef ImplicitMethodParameter Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint16_t getParameterIndex(); inline void setParameterIndex( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Type::AnyPointer::ImplicitMethodParameter::Pipeline { public: typedef ImplicitMethodParameter Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Brand::Reader { public: typedef Brand Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasScopes() const; inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader getScopes() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Brand::Builder { public: typedef Brand Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasScopes(); inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder getScopes(); inline void setScopes( ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder initScopes(unsigned int size); inline void adoptScopes(::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>> disownScopes(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Brand::Pipeline { public: typedef Brand Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Brand::Scope::Reader { public: typedef Scope Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline ::uint64_t getScopeId() const; inline bool isBind() const; inline bool hasBind() const; inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader getBind() const; inline bool isInherit() const; inline ::capnp::Void getInherit() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Brand::Scope::Builder { public: typedef Scope Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline ::uint64_t getScopeId(); inline void setScopeId( ::uint64_t value); inline bool isBind(); inline bool hasBind(); inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder getBind(); inline void setBind( ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder initBind(unsigned int size); inline void adoptBind(::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>> disownBind(); inline bool isInherit(); inline ::capnp::Void getInherit(); inline void setInherit( ::capnp::Void value = ::capnp::VOID); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Brand::Scope::Pipeline { public: typedef Scope Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Brand::Binding::Reader { public: typedef Binding Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnbound() const; inline ::capnp::Void getUnbound() const; inline bool isType() const; inline bool hasType() const; inline ::capnp::schema::Type::Reader getType() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Brand::Binding::Builder { public: typedef Binding Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnbound(); inline ::capnp::Void getUnbound(); inline void setUnbound( ::capnp::Void value = ::capnp::VOID); inline bool isType(); inline bool hasType(); inline ::capnp::schema::Type::Builder getType(); inline void setType( ::capnp::schema::Type::Reader value); inline ::capnp::schema::Type::Builder initType(); inline void adoptType(::capnp::Orphan< ::capnp::schema::Type>&& value); inline ::capnp::Orphan< ::capnp::schema::Type> disownType(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Brand::Binding::Pipeline { public: typedef Binding Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Value::Reader { public: typedef Value Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isVoid() const; inline ::capnp::Void getVoid() const; inline bool isBool() const; inline bool getBool() const; inline bool isInt8() const; inline ::int8_t getInt8() const; inline bool isInt16() const; inline ::int16_t getInt16() const; inline bool isInt32() const; inline ::int32_t getInt32() const; inline bool isInt64() const; inline ::int64_t getInt64() const; inline bool isUint8() const; inline ::uint8_t getUint8() const; inline bool isUint16() const; inline ::uint16_t getUint16() const; inline bool isUint32() const; inline ::uint32_t getUint32() const; inline bool isUint64() const; inline ::uint64_t getUint64() const; inline bool isFloat32() const; inline float getFloat32() const; inline bool isFloat64() const; inline double getFloat64() const; inline bool isText() const; inline bool hasText() const; inline ::capnp::Text::Reader getText() const; inline bool isData() const; inline bool hasData() const; inline ::capnp::Data::Reader getData() const; inline bool isList() const; inline bool hasList() const; inline ::capnp::AnyPointer::Reader getList() const; inline bool isEnum() const; inline ::uint16_t getEnum() const; inline bool isStruct() const; inline bool hasStruct() const; inline ::capnp::AnyPointer::Reader getStruct() const; inline bool isInterface() const; inline ::capnp::Void getInterface() const; inline bool isAnyPointer() const; inline bool hasAnyPointer() const; inline ::capnp::AnyPointer::Reader getAnyPointer() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Value::Builder { public: typedef Value Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isVoid(); inline ::capnp::Void getVoid(); inline void setVoid( ::capnp::Void value = ::capnp::VOID); inline bool isBool(); inline bool getBool(); inline void setBool(bool value); inline bool isInt8(); inline ::int8_t getInt8(); inline void setInt8( ::int8_t value); inline bool isInt16(); inline ::int16_t getInt16(); inline void setInt16( ::int16_t value); inline bool isInt32(); inline ::int32_t getInt32(); inline void setInt32( ::int32_t value); inline bool isInt64(); inline ::int64_t getInt64(); inline void setInt64( ::int64_t value); inline bool isUint8(); inline ::uint8_t getUint8(); inline void setUint8( ::uint8_t value); inline bool isUint16(); inline ::uint16_t getUint16(); inline void setUint16( ::uint16_t value); inline bool isUint32(); inline ::uint32_t getUint32(); inline void setUint32( ::uint32_t value); inline bool isUint64(); inline ::uint64_t getUint64(); inline void setUint64( ::uint64_t value); inline bool isFloat32(); inline float getFloat32(); inline void setFloat32(float value); inline bool isFloat64(); inline double getFloat64(); inline void setFloat64(double value); inline bool isText(); inline bool hasText(); inline ::capnp::Text::Builder getText(); inline void setText( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initText(unsigned int size); inline void adoptText(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownText(); inline bool isData(); inline bool hasData(); inline ::capnp::Data::Builder getData(); inline void setData( ::capnp::Data::Reader value); inline ::capnp::Data::Builder initData(unsigned int size); inline void adoptData(::capnp::Orphan< ::capnp::Data>&& value); inline ::capnp::Orphan< ::capnp::Data> disownData(); inline bool isList(); inline bool hasList(); inline ::capnp::AnyPointer::Builder getList(); inline ::capnp::AnyPointer::Builder initList(); inline bool isEnum(); inline ::uint16_t getEnum(); inline void setEnum( ::uint16_t value); inline bool isStruct(); inline bool hasStruct(); inline ::capnp::AnyPointer::Builder getStruct(); inline ::capnp::AnyPointer::Builder initStruct(); inline bool isInterface(); inline ::capnp::Void getInterface(); inline void setInterface( ::capnp::Void value = ::capnp::VOID); inline bool isAnyPointer(); inline bool hasAnyPointer(); inline ::capnp::AnyPointer::Builder getAnyPointer(); inline ::capnp::AnyPointer::Builder initAnyPointer(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Value::Pipeline { public: typedef Value Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Annotation::Reader { public: typedef Annotation Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getId() const; inline bool hasValue() const; inline ::capnp::schema::Value::Reader getValue() const; inline bool hasBrand() const; inline ::capnp::schema::Brand::Reader getBrand() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Annotation::Builder { public: typedef Annotation Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasValue(); inline ::capnp::schema::Value::Builder getValue(); inline void setValue( ::capnp::schema::Value::Reader value); inline ::capnp::schema::Value::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::schema::Value>&& value); inline ::capnp::Orphan< ::capnp::schema::Value> disownValue(); inline bool hasBrand(); inline ::capnp::schema::Brand::Builder getBrand(); inline void setBrand( ::capnp::schema::Brand::Reader value); inline ::capnp::schema::Brand::Builder initBrand(); inline void adoptBrand(::capnp::Orphan< ::capnp::schema::Brand>&& value); inline ::capnp::Orphan< ::capnp::schema::Brand> disownBrand(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Annotation::Pipeline { public: typedef Annotation Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::Value::Pipeline getValue(); inline ::capnp::schema::Brand::Pipeline getBrand(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CapnpVersion::Reader { public: typedef CapnpVersion Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint16_t getMajor() const; inline ::uint8_t getMinor() const; inline ::uint8_t getMicro() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CapnpVersion::Builder { public: typedef CapnpVersion Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint16_t getMajor(); inline void setMajor( ::uint16_t value); inline ::uint8_t getMinor(); inline void setMinor( ::uint8_t value); inline ::uint8_t getMicro(); inline void setMicro( ::uint8_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CapnpVersion::Pipeline { public: typedef CapnpVersion Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::Reader { public: typedef CodeGeneratorRequest Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasNodes() const; inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Reader getNodes() const; inline bool hasRequestedFiles() const; inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Reader getRequestedFiles() const; inline bool hasCapnpVersion() const; inline ::capnp::schema::CapnpVersion::Reader getCapnpVersion() const; inline bool hasSourceInfo() const; inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Reader getSourceInfo() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::Builder { public: typedef CodeGeneratorRequest Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasNodes(); inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Builder getNodes(); inline void setNodes( ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Builder initNodes(unsigned int size); inline void adoptNodes(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>> disownNodes(); inline bool hasRequestedFiles(); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Builder getRequestedFiles(); inline void setRequestedFiles( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Builder initRequestedFiles(unsigned int size); inline void adoptRequestedFiles(::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>> disownRequestedFiles(); inline bool hasCapnpVersion(); inline ::capnp::schema::CapnpVersion::Builder getCapnpVersion(); inline void setCapnpVersion( ::capnp::schema::CapnpVersion::Reader value); inline ::capnp::schema::CapnpVersion::Builder initCapnpVersion(); inline void adoptCapnpVersion(::capnp::Orphan< ::capnp::schema::CapnpVersion>&& value); inline ::capnp::Orphan< ::capnp::schema::CapnpVersion> disownCapnpVersion(); inline bool hasSourceInfo(); inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Builder getSourceInfo(); inline void setSourceInfo( ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Builder initSourceInfo(unsigned int size); inline void adoptSourceInfo(::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>> disownSourceInfo(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::Pipeline { public: typedef CodeGeneratorRequest Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::CapnpVersion::Pipeline getCapnpVersion(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::Reader { public: typedef RequestedFile Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getId() const; inline bool hasFilename() const; inline ::capnp::Text::Reader getFilename() const; inline bool hasImports() const; inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Reader getImports() const; inline bool hasFileSourceInfo() const; inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader getFileSourceInfo() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::RequestedFile::Builder { public: typedef RequestedFile Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasFilename(); inline ::capnp::Text::Builder getFilename(); inline void setFilename( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initFilename(unsigned int size); inline void adoptFilename(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownFilename(); inline bool hasImports(); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Builder getImports(); inline void setImports( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Builder initImports(unsigned int size); inline void adoptImports(::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>> disownImports(); inline bool hasFileSourceInfo(); inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder getFileSourceInfo(); inline void setFileSourceInfo( ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader value); inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder initFileSourceInfo(); inline void adoptFileSourceInfo(::capnp::Orphan< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>&& value); inline ::capnp::Orphan< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo> disownFileSourceInfo(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::Pipeline { public: typedef RequestedFile Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Pipeline getFileSourceInfo(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::Import::Reader { public: typedef Import Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getId() const; inline bool hasName() const; inline ::capnp::Text::Reader getName() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::RequestedFile::Import::Builder { public: typedef Import Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getId(); inline void setId( ::uint64_t value); inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::Import::Pipeline { public: typedef Import Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader { public: typedef FileSourceInfo Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasIdentifiers() const; inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Reader getIdentifiers() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder { public: typedef FileSourceInfo Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasIdentifiers(); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Builder getIdentifiers(); inline void setIdentifiers( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Builder initIdentifiers(unsigned int size); inline void adoptIdentifiers(::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>> disownIdentifiers(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Pipeline { public: typedef FileSourceInfo Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader { public: typedef Identifier Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline ::uint32_t getStartByte() const; inline ::uint32_t getEndByte() const; inline bool isTypeId() const; inline ::uint64_t getTypeId() const; inline bool isMember() const; inline typename Member::Reader getMember() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder { public: typedef Identifier Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline ::uint32_t getStartByte(); inline void setStartByte( ::uint32_t value); inline ::uint32_t getEndByte(); inline void setEndByte( ::uint32_t value); inline bool isTypeId(); inline ::uint64_t getTypeId(); inline void setTypeId( ::uint64_t value); inline bool isMember(); inline typename Member::Builder getMember(); inline typename Member::Builder initMember(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Pipeline { public: typedef Identifier Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Reader { public: typedef Member Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint64_t getParentTypeId() const; inline ::uint16_t getOrdinal() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder { public: typedef Member Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint64_t getParentTypeId(); inline void setParentTypeId( ::uint64_t value); inline ::uint16_t getOrdinal(); inline void setOrdinal( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Pipeline { public: typedef Member Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline ::capnp::schema::Node::Which Node::Reader::which() const { return _reader.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Node::Which Node::Builder::which() { return _builder.getDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline ::uint64_t Node::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Node::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Node::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Node::Reader::hasDisplayName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Node::Builder::hasDisplayName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::Reader::getDisplayName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::Builder::getDisplayName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Node::Builder::setDisplayName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::Builder::initDisplayName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Node::Builder::adoptDisplayName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::Builder::disownDisplayName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Node::Reader::getDisplayNamePrefixLength() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::Builder::getDisplayNamePrefixLength() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Node::Builder::setDisplayNamePrefixLength( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Node::Reader::getScopeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint64_t Node::Builder::getScopeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Node::Builder::setScopeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Node::Reader::hasNestedNodes() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Node::Builder::hasNestedNodes() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader Node::Reader::getNestedNodes() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder Node::Builder::getNestedNodes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Node::Builder::setNestedNodes( ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>::Builder Node::Builder::initNestedNodes(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Node::Builder::adoptNestedNodes( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>> Node::Builder::disownNestedNodes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::NestedNode, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Node::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Node::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Node::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Node::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Node::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Node::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), size); } inline void Node::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Node::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline bool Node::Reader::isFile() const { return which() == Node::FILE; } inline bool Node::Builder::isFile() { return which() == Node::FILE; } inline ::capnp::Void Node::Reader::getFile() const { KJ_IREQUIRE((which() == Node::FILE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Node::Builder::getFile() { KJ_IREQUIRE((which() == Node::FILE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Node::Builder::setFile( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::FILE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Node::Reader::isStruct() const { return which() == Node::STRUCT; } inline bool Node::Builder::isStruct() { return which() == Node::STRUCT; } inline typename Node::Struct::Reader Node::Reader::getStruct() const { KJ_IREQUIRE((which() == Node::STRUCT), "Must check which() before get()ing a union member."); return typename Node::Struct::Reader(_reader); } inline typename Node::Struct::Builder Node::Builder::getStruct() { KJ_IREQUIRE((which() == Node::STRUCT), "Must check which() before get()ing a union member."); return typename Node::Struct::Builder(_builder); } inline typename Node::Struct::Builder Node::Builder::initStruct() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::STRUCT); _builder.setDataField< ::uint16_t>(::capnp::bounded<7>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<12>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<13>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<224>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<15>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint32_t>(::capnp::bounded<8>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); return typename Node::Struct::Builder(_builder); } inline bool Node::Reader::isEnum() const { return which() == Node::ENUM; } inline bool Node::Builder::isEnum() { return which() == Node::ENUM; } inline typename Node::Enum::Reader Node::Reader::getEnum() const { KJ_IREQUIRE((which() == Node::ENUM), "Must check which() before get()ing a union member."); return typename Node::Enum::Reader(_reader); } inline typename Node::Enum::Builder Node::Builder::getEnum() { KJ_IREQUIRE((which() == Node::ENUM), "Must check which() before get()ing a union member."); return typename Node::Enum::Builder(_builder); } inline typename Node::Enum::Builder Node::Builder::initEnum() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::ENUM); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); return typename Node::Enum::Builder(_builder); } inline bool Node::Reader::isInterface() const { return which() == Node::INTERFACE; } inline bool Node::Builder::isInterface() { return which() == Node::INTERFACE; } inline typename Node::Interface::Reader Node::Reader::getInterface() const { KJ_IREQUIRE((which() == Node::INTERFACE), "Must check which() before get()ing a union member."); return typename Node::Interface::Reader(_reader); } inline typename Node::Interface::Builder Node::Builder::getInterface() { KJ_IREQUIRE((which() == Node::INTERFACE), "Must check which() before get()ing a union member."); return typename Node::Interface::Builder(_builder); } inline typename Node::Interface::Builder Node::Builder::initInterface() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::INTERFACE); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear(); return typename Node::Interface::Builder(_builder); } inline bool Node::Reader::isConst() const { return which() == Node::CONST; } inline bool Node::Builder::isConst() { return which() == Node::CONST; } inline typename Node::Const::Reader Node::Reader::getConst() const { KJ_IREQUIRE((which() == Node::CONST), "Must check which() before get()ing a union member."); return typename Node::Const::Reader(_reader); } inline typename Node::Const::Builder Node::Builder::getConst() { KJ_IREQUIRE((which() == Node::CONST), "Must check which() before get()ing a union member."); return typename Node::Const::Builder(_builder); } inline typename Node::Const::Builder Node::Builder::initConst() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::CONST); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear(); return typename Node::Const::Builder(_builder); } inline bool Node::Reader::isAnnotation() const { return which() == Node::ANNOTATION; } inline bool Node::Builder::isAnnotation() { return which() == Node::ANNOTATION; } inline typename Node::Annotation::Reader Node::Reader::getAnnotation() const { KJ_IREQUIRE((which() == Node::ANNOTATION), "Must check which() before get()ing a union member."); return typename Node::Annotation::Reader(_reader); } inline typename Node::Annotation::Builder Node::Builder::getAnnotation() { KJ_IREQUIRE((which() == Node::ANNOTATION), "Must check which() before get()ing a union member."); return typename Node::Annotation::Builder(_builder); } inline typename Node::Annotation::Builder Node::Builder::initAnnotation() { _builder.setDataField( ::capnp::bounded<6>() * ::capnp::ELEMENTS, Node::ANNOTATION); _builder.setDataField(::capnp::bounded<112>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<113>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<114>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<115>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<116>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<117>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<118>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<119>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<120>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<121>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<122>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<123>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); return typename Node::Annotation::Builder(_builder); } inline bool Node::Reader::hasParameters() const { return !_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline bool Node::Builder::hasParameters() { return !_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader Node::Reader::getParameters() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Node::Builder::getParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline void Node::Builder::setParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Node::Builder::initParameters(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), size); } inline void Node::Builder::adoptParameters( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> Node::Builder::disownParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<5>() * ::capnp::POINTERS)); } inline bool Node::Reader::getIsGeneric() const { return _reader.getDataField( ::capnp::bounded<288>() * ::capnp::ELEMENTS); } inline bool Node::Builder::getIsGeneric() { return _builder.getDataField( ::capnp::bounded<288>() * ::capnp::ELEMENTS); } inline void Node::Builder::setIsGeneric(bool value) { _builder.setDataField( ::capnp::bounded<288>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Node::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<10>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<10>() * ::capnp::ELEMENTS); } inline void Node::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<10>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Node::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<11>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<11>() * ::capnp::ELEMENTS); } inline void Node::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<11>() * ::capnp::ELEMENTS, value); } inline bool Node::Parameter::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Node::Parameter::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::Parameter::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::Parameter::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Node::Parameter::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::Parameter::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Node::Parameter::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::Parameter::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Node::NestedNode::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Node::NestedNode::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::NestedNode::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::NestedNode::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Node::NestedNode::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::NestedNode::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Node::NestedNode::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::NestedNode::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint64_t Node::NestedNode::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Node::NestedNode::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Node::NestedNode::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Node::SourceInfo::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Node::SourceInfo::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Node::SourceInfo::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Node::SourceInfo::Reader::hasDocComment() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Node::SourceInfo::Builder::hasDocComment() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::SourceInfo::Reader::getDocComment() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::SourceInfo::Builder::getDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Node::SourceInfo::Builder::setDocComment( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::SourceInfo::Builder::initDocComment(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Node::SourceInfo::Builder::adoptDocComment( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::SourceInfo::Builder::disownDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Node::SourceInfo::Reader::hasMembers() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Node::SourceInfo::Builder::hasMembers() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Reader Node::SourceInfo::Reader::getMembers() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Builder Node::SourceInfo::Builder::getMembers() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Node::SourceInfo::Builder::setMembers( ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>::Builder Node::SourceInfo::Builder::initMembers(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Node::SourceInfo::Builder::adoptMembers( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>> Node::SourceInfo::Builder::disownMembers() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo::Member, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::uint32_t Node::SourceInfo::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::SourceInfo::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Node::SourceInfo::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Node::SourceInfo::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::SourceInfo::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline void Node::SourceInfo::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); } inline bool Node::SourceInfo::Member::Reader::hasDocComment() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Node::SourceInfo::Member::Builder::hasDocComment() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::SourceInfo::Member::Reader::getDocComment() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::SourceInfo::Member::Builder::getDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Node::SourceInfo::Member::Builder::setDocComment( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::SourceInfo::Member::Builder::initDocComment(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Node::SourceInfo::Member::Builder::adoptDocComment( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::SourceInfo::Member::Builder::disownDocComment() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Node::SourceInfo::Member::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::SourceInfo::Member::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Node::SourceInfo::Member::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Node::SourceInfo::Member::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::SourceInfo::Member::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Node::SourceInfo::Member::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Node::SourceInfo::Member::Reader::hasTypeId() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Node::SourceInfo::Member::Builder::hasTypeId() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Node::SourceInfo::Member::Reader::getTypeId() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Node::SourceInfo::Member::Builder::getTypeId() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Node::SourceInfo::Member::Builder::setTypeId( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Node::SourceInfo::Member::Builder::initTypeId(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Node::SourceInfo::Member::Builder::adoptTypeId( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Node::SourceInfo::Member::Builder::disownTypeId() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::uint16_t Node::Struct::Reader::getDataWordCount() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<7>() * ::capnp::ELEMENTS); } inline ::uint16_t Node::Struct::Builder::getDataWordCount() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<7>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setDataWordCount( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<7>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Node::Struct::Reader::getPointerCount() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<12>() * ::capnp::ELEMENTS); } inline ::uint16_t Node::Struct::Builder::getPointerCount() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<12>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setPointerCount( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<12>() * ::capnp::ELEMENTS, value); } inline ::capnp::schema::ElementSize Node::Struct::Reader::getPreferredListEncoding() const { return _reader.getDataField< ::capnp::schema::ElementSize>( ::capnp::bounded<13>() * ::capnp::ELEMENTS); } inline ::capnp::schema::ElementSize Node::Struct::Builder::getPreferredListEncoding() { return _builder.getDataField< ::capnp::schema::ElementSize>( ::capnp::bounded<13>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setPreferredListEncoding( ::capnp::schema::ElementSize value) { _builder.setDataField< ::capnp::schema::ElementSize>( ::capnp::bounded<13>() * ::capnp::ELEMENTS, value); } inline bool Node::Struct::Reader::getIsGroup() const { return _reader.getDataField( ::capnp::bounded<224>() * ::capnp::ELEMENTS); } inline bool Node::Struct::Builder::getIsGroup() { return _builder.getDataField( ::capnp::bounded<224>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setIsGroup(bool value) { _builder.setDataField( ::capnp::bounded<224>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Node::Struct::Reader::getDiscriminantCount() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<15>() * ::capnp::ELEMENTS); } inline ::uint16_t Node::Struct::Builder::getDiscriminantCount() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<15>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setDiscriminantCount( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<15>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Node::Struct::Reader::getDiscriminantOffset() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<8>() * ::capnp::ELEMENTS); } inline ::uint32_t Node::Struct::Builder::getDiscriminantOffset() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<8>() * ::capnp::ELEMENTS); } inline void Node::Struct::Builder::setDiscriminantOffset( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<8>() * ::capnp::ELEMENTS, value); } inline bool Node::Struct::Reader::hasFields() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Node::Struct::Builder::hasFields() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader Node::Struct::Reader::getFields() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder Node::Struct::Builder::getFields() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Node::Struct::Builder::setFields( ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>::Builder Node::Struct::Builder::initFields(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), size); } inline void Node::Struct::Builder::adoptFields( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>> Node::Struct::Builder::disownFields() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Field, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Node::Enum::Reader::hasEnumerants() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Node::Enum::Builder::hasEnumerants() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader Node::Enum::Reader::getEnumerants() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder Node::Enum::Builder::getEnumerants() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Node::Enum::Builder::setEnumerants( ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>::Builder Node::Enum::Builder::initEnumerants(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), size); } inline void Node::Enum::Builder::adoptEnumerants( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>> Node::Enum::Builder::disownEnumerants() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Enumerant, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Node::Interface::Reader::hasMethods() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Node::Interface::Builder::hasMethods() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader Node::Interface::Reader::getMethods() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::getMethods() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Node::Interface::Builder::setMethods( ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::initMethods(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), size); } inline void Node::Interface::Builder::adoptMethods( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>> Node::Interface::Builder::disownMethods() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Method, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Node::Interface::Reader::hasSuperclasses() const { return !_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline bool Node::Interface::Builder::hasSuperclasses() { return !_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader Node::Interface::Reader::getSuperclasses() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::getSuperclasses() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline void Node::Interface::Builder::setSuperclasses( ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>::Builder Node::Interface::Builder::initSuperclasses(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), size); } inline void Node::Interface::Builder::adoptSuperclasses( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>> Node::Interface::Builder::disownSuperclasses() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Superclass, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline bool Node::Const::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Node::Const::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Type::Reader Node::Const::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Builder Node::Const::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Type::Pipeline Node::Const::Pipeline::getType() { return ::capnp::schema::Type::Pipeline(_typeless.getPointerField(3)); } #endif // !CAPNP_LITE inline void Node::Const::Builder::setType( ::capnp::schema::Type::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Type::Builder Node::Const::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Node::Const::Builder::adoptType( ::capnp::Orphan< ::capnp::schema::Type>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Type> Node::Const::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Node::Const::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline bool Node::Const::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Value::Reader Node::Const::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline ::capnp::schema::Value::Builder Node::Const::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Value::Pipeline Node::Const::Pipeline::getValue() { return ::capnp::schema::Value::Pipeline(_typeless.getPointerField(4)); } #endif // !CAPNP_LITE inline void Node::Const::Builder::setValue( ::capnp::schema::Value::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Value::Builder Node::Const::Builder::initValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline void Node::Const::Builder::adoptValue( ::capnp::Orphan< ::capnp::schema::Value>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Value> Node::Const::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline bool Node::Annotation::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Node::Annotation::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Type::Reader Node::Annotation::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Builder Node::Annotation::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Type::Pipeline Node::Annotation::Pipeline::getType() { return ::capnp::schema::Type::Pipeline(_typeless.getPointerField(3)); } #endif // !CAPNP_LITE inline void Node::Annotation::Builder::setType( ::capnp::schema::Type::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Type::Builder Node::Annotation::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Node::Annotation::Builder::adoptType( ::capnp::Orphan< ::capnp::schema::Type>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Type> Node::Annotation::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Node::Annotation::Reader::getTargetsFile() const { return _reader.getDataField( ::capnp::bounded<112>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsFile() { return _builder.getDataField( ::capnp::bounded<112>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsFile(bool value) { _builder.setDataField( ::capnp::bounded<112>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsConst() const { return _reader.getDataField( ::capnp::bounded<113>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsConst() { return _builder.getDataField( ::capnp::bounded<113>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsConst(bool value) { _builder.setDataField( ::capnp::bounded<113>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsEnum() const { return _reader.getDataField( ::capnp::bounded<114>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsEnum() { return _builder.getDataField( ::capnp::bounded<114>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsEnum(bool value) { _builder.setDataField( ::capnp::bounded<114>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsEnumerant() const { return _reader.getDataField( ::capnp::bounded<115>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsEnumerant() { return _builder.getDataField( ::capnp::bounded<115>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsEnumerant(bool value) { _builder.setDataField( ::capnp::bounded<115>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsStruct() const { return _reader.getDataField( ::capnp::bounded<116>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsStruct() { return _builder.getDataField( ::capnp::bounded<116>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsStruct(bool value) { _builder.setDataField( ::capnp::bounded<116>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsField() const { return _reader.getDataField( ::capnp::bounded<117>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsField() { return _builder.getDataField( ::capnp::bounded<117>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsField(bool value) { _builder.setDataField( ::capnp::bounded<117>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsUnion() const { return _reader.getDataField( ::capnp::bounded<118>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsUnion() { return _builder.getDataField( ::capnp::bounded<118>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsUnion(bool value) { _builder.setDataField( ::capnp::bounded<118>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsGroup() const { return _reader.getDataField( ::capnp::bounded<119>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsGroup() { return _builder.getDataField( ::capnp::bounded<119>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsGroup(bool value) { _builder.setDataField( ::capnp::bounded<119>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsInterface() const { return _reader.getDataField( ::capnp::bounded<120>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsInterface() { return _builder.getDataField( ::capnp::bounded<120>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsInterface(bool value) { _builder.setDataField( ::capnp::bounded<120>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsMethod() const { return _reader.getDataField( ::capnp::bounded<121>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsMethod() { return _builder.getDataField( ::capnp::bounded<121>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsMethod(bool value) { _builder.setDataField( ::capnp::bounded<121>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsParam() const { return _reader.getDataField( ::capnp::bounded<122>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsParam() { return _builder.getDataField( ::capnp::bounded<122>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsParam(bool value) { _builder.setDataField( ::capnp::bounded<122>() * ::capnp::ELEMENTS, value); } inline bool Node::Annotation::Reader::getTargetsAnnotation() const { return _reader.getDataField( ::capnp::bounded<123>() * ::capnp::ELEMENTS); } inline bool Node::Annotation::Builder::getTargetsAnnotation() { return _builder.getDataField( ::capnp::bounded<123>() * ::capnp::ELEMENTS); } inline void Node::Annotation::Builder::setTargetsAnnotation(bool value) { _builder.setDataField( ::capnp::bounded<123>() * ::capnp::ELEMENTS, value); } inline ::capnp::schema::Field::Which Field::Reader::which() const { return _reader.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Field::Which Field::Builder::which() { return _builder.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline bool Field::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Field::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Field::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Field::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Field::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Field::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Field::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Field::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint16_t Field::Reader::getCodeOrder() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint16_t Field::Builder::getCodeOrder() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Field::Builder::setCodeOrder( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Field::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Field::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Field::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Field::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Field::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Field::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Field::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Field::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::uint16_t Field::Reader::getDiscriminantValue() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, 65535u); } inline ::uint16_t Field::Builder::getDiscriminantValue() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, 65535u); } inline void Field::Builder::setDiscriminantValue( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value, 65535u); } inline bool Field::Reader::isSlot() const { return which() == Field::SLOT; } inline bool Field::Builder::isSlot() { return which() == Field::SLOT; } inline typename Field::Slot::Reader Field::Reader::getSlot() const { KJ_IREQUIRE((which() == Field::SLOT), "Must check which() before get()ing a union member."); return typename Field::Slot::Reader(_reader); } inline typename Field::Slot::Builder Field::Builder::getSlot() { KJ_IREQUIRE((which() == Field::SLOT), "Must check which() before get()ing a union member."); return typename Field::Slot::Builder(_builder); } inline typename Field::Slot::Builder Field::Builder::initSlot() { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Field::SLOT); _builder.setDataField< ::uint32_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); _builder.setDataField(::capnp::bounded<128>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<3>() * ::capnp::POINTERS).clear(); return typename Field::Slot::Builder(_builder); } inline bool Field::Reader::isGroup() const { return which() == Field::GROUP; } inline bool Field::Builder::isGroup() { return which() == Field::GROUP; } inline typename Field::Group::Reader Field::Reader::getGroup() const { KJ_IREQUIRE((which() == Field::GROUP), "Must check which() before get()ing a union member."); return typename Field::Group::Reader(_reader); } inline typename Field::Group::Builder Field::Builder::getGroup() { KJ_IREQUIRE((which() == Field::GROUP), "Must check which() before get()ing a union member."); return typename Field::Group::Builder(_builder); } inline typename Field::Group::Builder Field::Builder::initGroup() { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Field::GROUP); _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); return typename Field::Group::Builder(_builder); } inline typename Field::Ordinal::Reader Field::Reader::getOrdinal() const { return typename Field::Ordinal::Reader(_reader); } inline typename Field::Ordinal::Builder Field::Builder::getOrdinal() { return typename Field::Ordinal::Builder(_builder); } #if !CAPNP_LITE inline typename Field::Ordinal::Pipeline Field::Pipeline::getOrdinal() { return typename Field::Ordinal::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Field::Ordinal::Builder Field::Builder::initOrdinal() { _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); return typename Field::Ordinal::Builder(_builder); } inline ::uint32_t Field::Slot::Reader::getOffset() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Field::Slot::Builder::getOffset() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Field::Slot::Builder::setOffset( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Field::Slot::Reader::hasType() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Field::Slot::Builder::hasType() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Type::Reader Field::Slot::Reader::getType() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Builder Field::Slot::Builder::getType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Type::Pipeline Field::Slot::Pipeline::getType() { return ::capnp::schema::Type::Pipeline(_typeless.getPointerField(2)); } #endif // !CAPNP_LITE inline void Field::Slot::Builder::setType( ::capnp::schema::Type::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Type::Builder Field::Slot::Builder::initType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Field::Slot::Builder::adoptType( ::capnp::Orphan< ::capnp::schema::Type>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Type> Field::Slot::Builder::disownType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline bool Field::Slot::Reader::hasDefaultValue() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Field::Slot::Builder::hasDefaultValue() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Value::Reader Field::Slot::Reader::getDefaultValue() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::schema::Value::Builder Field::Slot::Builder::getDefaultValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Value::Pipeline Field::Slot::Pipeline::getDefaultValue() { return ::capnp::schema::Value::Pipeline(_typeless.getPointerField(3)); } #endif // !CAPNP_LITE inline void Field::Slot::Builder::setDefaultValue( ::capnp::schema::Value::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Value::Builder Field::Slot::Builder::initDefaultValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Field::Slot::Builder::adoptDefaultValue( ::capnp::Orphan< ::capnp::schema::Value>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Value> Field::Slot::Builder::disownDefaultValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Field::Slot::Reader::getHadExplicitDefault() const { return _reader.getDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS); } inline bool Field::Slot::Builder::getHadExplicitDefault() { return _builder.getDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS); } inline void Field::Slot::Builder::setHadExplicitDefault(bool value) { _builder.setDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Field::Group::Reader::getTypeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint64_t Field::Group::Builder::getTypeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Field::Group::Builder::setTypeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::capnp::schema::Field::Ordinal::Which Field::Ordinal::Reader::which() const { return _reader.getDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Field::Ordinal::Which Field::Ordinal::Builder::which() { return _builder.getDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline bool Field::Ordinal::Reader::isImplicit() const { return which() == Field::Ordinal::IMPLICIT; } inline bool Field::Ordinal::Builder::isImplicit() { return which() == Field::Ordinal::IMPLICIT; } inline ::capnp::Void Field::Ordinal::Reader::getImplicit() const { KJ_IREQUIRE((which() == Field::Ordinal::IMPLICIT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Field::Ordinal::Builder::getImplicit() { KJ_IREQUIRE((which() == Field::Ordinal::IMPLICIT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Field::Ordinal::Builder::setImplicit( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Field::Ordinal::IMPLICIT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Field::Ordinal::Reader::isExplicit() const { return which() == Field::Ordinal::EXPLICIT; } inline bool Field::Ordinal::Builder::isExplicit() { return which() == Field::Ordinal::EXPLICIT; } inline ::uint16_t Field::Ordinal::Reader::getExplicit() const { KJ_IREQUIRE((which() == Field::Ordinal::EXPLICIT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint16_t>( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline ::uint16_t Field::Ordinal::Builder::getExplicit() { KJ_IREQUIRE((which() == Field::Ordinal::EXPLICIT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint16_t>( ::capnp::bounded<6>() * ::capnp::ELEMENTS); } inline void Field::Ordinal::Builder::setExplicit( ::uint16_t value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Field::Ordinal::EXPLICIT); _builder.setDataField< ::uint16_t>( ::capnp::bounded<6>() * ::capnp::ELEMENTS, value); } inline bool Enumerant::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Enumerant::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Enumerant::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Enumerant::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Enumerant::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Enumerant::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Enumerant::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Enumerant::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint16_t Enumerant::Reader::getCodeOrder() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint16_t Enumerant::Builder::getCodeOrder() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Enumerant::Builder::setCodeOrder( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Enumerant::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Enumerant::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Enumerant::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Enumerant::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Enumerant::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Enumerant::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Enumerant::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Enumerant::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::uint64_t Superclass::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Superclass::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Superclass::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Superclass::Reader::hasBrand() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Superclass::Builder::hasBrand() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Superclass::Reader::getBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Superclass::Builder::getBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Superclass::Pipeline::getBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Superclass::Builder::setBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Superclass::Builder::initBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Superclass::Builder::adoptBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Superclass::Builder::disownBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Method::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Method::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Method::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Method::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Method::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Method::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Method::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Method::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint16_t Method::Reader::getCodeOrder() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint16_t Method::Builder::getCodeOrder() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Method::Builder::setCodeOrder( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Method::Reader::getParamStructType() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Method::Builder::getParamStructType() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Method::Builder::setParamStructType( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Method::Reader::getResultStructType() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint64_t Method::Builder::getResultStructType() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Method::Builder::setResultStructType( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Method::Reader::hasAnnotations() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Method::Builder::hasAnnotations() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader Method::Reader::getAnnotations() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Method::Builder::getAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Method::Builder::setAnnotations( ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>::Builder Method::Builder::initAnnotations(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Method::Builder::adoptAnnotations( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>> Method::Builder::disownAnnotations() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Annotation, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Method::Reader::hasParamBrand() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Method::Builder::hasParamBrand() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Method::Reader::getParamBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Method::Builder::getParamBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Method::Pipeline::getParamBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(2)); } #endif // !CAPNP_LITE inline void Method::Builder::setParamBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Method::Builder::initParamBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void Method::Builder::adoptParamBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Method::Builder::disownParamBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline bool Method::Reader::hasResultBrand() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool Method::Builder::hasResultBrand() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Method::Reader::getResultBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Method::Builder::getResultBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Method::Pipeline::getResultBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(3)); } #endif // !CAPNP_LITE inline void Method::Builder::setResultBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Method::Builder::initResultBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void Method::Builder::adoptResultBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Method::Builder::disownResultBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline bool Method::Reader::hasImplicitParameters() const { return !_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline bool Method::Builder::hasImplicitParameters() { return !_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader Method::Reader::getImplicitParameters() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Method::Builder::getImplicitParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline void Method::Builder::setImplicitParameters( ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>::Builder Method::Builder::initImplicitParameters(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), size); } inline void Method::Builder::adoptImplicitParameters( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>> Method::Builder::disownImplicitParameters() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::Parameter, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<4>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Which Type::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Type::Which Type::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Type::Reader::isVoid() const { return which() == Type::VOID; } inline bool Type::Builder::isVoid() { return which() == Type::VOID; } inline ::capnp::Void Type::Reader::getVoid() const { KJ_IREQUIRE((which() == Type::VOID), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getVoid() { KJ_IREQUIRE((which() == Type::VOID), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setVoid( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::VOID); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isBool() const { return which() == Type::BOOL; } inline bool Type::Builder::isBool() { return which() == Type::BOOL; } inline ::capnp::Void Type::Reader::getBool() const { KJ_IREQUIRE((which() == Type::BOOL), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getBool() { KJ_IREQUIRE((which() == Type::BOOL), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setBool( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::BOOL); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isInt8() const { return which() == Type::INT8; } inline bool Type::Builder::isInt8() { return which() == Type::INT8; } inline ::capnp::Void Type::Reader::getInt8() const { KJ_IREQUIRE((which() == Type::INT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getInt8() { KJ_IREQUIRE((which() == Type::INT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setInt8( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT8); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isInt16() const { return which() == Type::INT16; } inline bool Type::Builder::isInt16() { return which() == Type::INT16; } inline ::capnp::Void Type::Reader::getInt16() const { KJ_IREQUIRE((which() == Type::INT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getInt16() { KJ_IREQUIRE((which() == Type::INT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setInt16( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT16); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isInt32() const { return which() == Type::INT32; } inline bool Type::Builder::isInt32() { return which() == Type::INT32; } inline ::capnp::Void Type::Reader::getInt32() const { KJ_IREQUIRE((which() == Type::INT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getInt32() { KJ_IREQUIRE((which() == Type::INT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setInt32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isInt64() const { return which() == Type::INT64; } inline bool Type::Builder::isInt64() { return which() == Type::INT64; } inline ::capnp::Void Type::Reader::getInt64() const { KJ_IREQUIRE((which() == Type::INT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getInt64() { KJ_IREQUIRE((which() == Type::INT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setInt64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isUint8() const { return which() == Type::UINT8; } inline bool Type::Builder::isUint8() { return which() == Type::UINT8; } inline ::capnp::Void Type::Reader::getUint8() const { KJ_IREQUIRE((which() == Type::UINT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getUint8() { KJ_IREQUIRE((which() == Type::UINT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setUint8( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT8); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isUint16() const { return which() == Type::UINT16; } inline bool Type::Builder::isUint16() { return which() == Type::UINT16; } inline ::capnp::Void Type::Reader::getUint16() const { KJ_IREQUIRE((which() == Type::UINT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getUint16() { KJ_IREQUIRE((which() == Type::UINT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setUint16( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT16); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isUint32() const { return which() == Type::UINT32; } inline bool Type::Builder::isUint32() { return which() == Type::UINT32; } inline ::capnp::Void Type::Reader::getUint32() const { KJ_IREQUIRE((which() == Type::UINT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getUint32() { KJ_IREQUIRE((which() == Type::UINT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setUint32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isUint64() const { return which() == Type::UINT64; } inline bool Type::Builder::isUint64() { return which() == Type::UINT64; } inline ::capnp::Void Type::Reader::getUint64() const { KJ_IREQUIRE((which() == Type::UINT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getUint64() { KJ_IREQUIRE((which() == Type::UINT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setUint64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::UINT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isFloat32() const { return which() == Type::FLOAT32; } inline bool Type::Builder::isFloat32() { return which() == Type::FLOAT32; } inline ::capnp::Void Type::Reader::getFloat32() const { KJ_IREQUIRE((which() == Type::FLOAT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getFloat32() { KJ_IREQUIRE((which() == Type::FLOAT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setFloat32( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::FLOAT32); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isFloat64() const { return which() == Type::FLOAT64; } inline bool Type::Builder::isFloat64() { return which() == Type::FLOAT64; } inline ::capnp::Void Type::Reader::getFloat64() const { KJ_IREQUIRE((which() == Type::FLOAT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getFloat64() { KJ_IREQUIRE((which() == Type::FLOAT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setFloat64( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::FLOAT64); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isText() const { return which() == Type::TEXT; } inline bool Type::Builder::isText() { return which() == Type::TEXT; } inline ::capnp::Void Type::Reader::getText() const { KJ_IREQUIRE((which() == Type::TEXT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getText() { KJ_IREQUIRE((which() == Type::TEXT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setText( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::TEXT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isData() const { return which() == Type::DATA; } inline bool Type::Builder::isData() { return which() == Type::DATA; } inline ::capnp::Void Type::Reader::getData() const { KJ_IREQUIRE((which() == Type::DATA), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::Builder::getData() { KJ_IREQUIRE((which() == Type::DATA), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::Builder::setData( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::DATA); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::Reader::isList() const { return which() == Type::LIST; } inline bool Type::Builder::isList() { return which() == Type::LIST; } inline typename Type::List::Reader Type::Reader::getList() const { KJ_IREQUIRE((which() == Type::LIST), "Must check which() before get()ing a union member."); return typename Type::List::Reader(_reader); } inline typename Type::List::Builder Type::Builder::getList() { KJ_IREQUIRE((which() == Type::LIST), "Must check which() before get()ing a union member."); return typename Type::List::Builder(_builder); } inline typename Type::List::Builder Type::Builder::initList() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::LIST); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); return typename Type::List::Builder(_builder); } inline bool Type::Reader::isEnum() const { return which() == Type::ENUM; } inline bool Type::Builder::isEnum() { return which() == Type::ENUM; } inline typename Type::Enum::Reader Type::Reader::getEnum() const { KJ_IREQUIRE((which() == Type::ENUM), "Must check which() before get()ing a union member."); return typename Type::Enum::Reader(_reader); } inline typename Type::Enum::Builder Type::Builder::getEnum() { KJ_IREQUIRE((which() == Type::ENUM), "Must check which() before get()ing a union member."); return typename Type::Enum::Builder(_builder); } inline typename Type::Enum::Builder Type::Builder::initEnum() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::ENUM); _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); return typename Type::Enum::Builder(_builder); } inline bool Type::Reader::isStruct() const { return which() == Type::STRUCT; } inline bool Type::Builder::isStruct() { return which() == Type::STRUCT; } inline typename Type::Struct::Reader Type::Reader::getStruct() const { KJ_IREQUIRE((which() == Type::STRUCT), "Must check which() before get()ing a union member."); return typename Type::Struct::Reader(_reader); } inline typename Type::Struct::Builder Type::Builder::getStruct() { KJ_IREQUIRE((which() == Type::STRUCT), "Must check which() before get()ing a union member."); return typename Type::Struct::Builder(_builder); } inline typename Type::Struct::Builder Type::Builder::initStruct() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::STRUCT); _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); return typename Type::Struct::Builder(_builder); } inline bool Type::Reader::isInterface() const { return which() == Type::INTERFACE; } inline bool Type::Builder::isInterface() { return which() == Type::INTERFACE; } inline typename Type::Interface::Reader Type::Reader::getInterface() const { KJ_IREQUIRE((which() == Type::INTERFACE), "Must check which() before get()ing a union member."); return typename Type::Interface::Reader(_reader); } inline typename Type::Interface::Builder Type::Builder::getInterface() { KJ_IREQUIRE((which() == Type::INTERFACE), "Must check which() before get()ing a union member."); return typename Type::Interface::Builder(_builder); } inline typename Type::Interface::Builder Type::Builder::initInterface() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::INTERFACE); _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<0>() * ::capnp::POINTERS).clear(); return typename Type::Interface::Builder(_builder); } inline bool Type::Reader::isAnyPointer() const { return which() == Type::ANY_POINTER; } inline bool Type::Builder::isAnyPointer() { return which() == Type::ANY_POINTER; } inline typename Type::AnyPointer::Reader Type::Reader::getAnyPointer() const { KJ_IREQUIRE((which() == Type::ANY_POINTER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Reader(_reader); } inline typename Type::AnyPointer::Builder Type::Builder::getAnyPointer() { KJ_IREQUIRE((which() == Type::ANY_POINTER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Builder(_builder); } inline typename Type::AnyPointer::Builder Type::Builder::initAnyPointer() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Type::ANY_POINTER); _builder.setDataField< ::uint16_t>(::capnp::bounded<4>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); return typename Type::AnyPointer::Builder(_builder); } inline bool Type::List::Reader::hasElementType() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Type::List::Builder::hasElementType() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Type::Reader Type::List::Reader::getElementType() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Builder Type::List::Builder::getElementType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Type::Pipeline Type::List::Pipeline::getElementType() { return ::capnp::schema::Type::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Type::List::Builder::setElementType( ::capnp::schema::Type::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Type::Builder Type::List::Builder::initElementType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Type::List::Builder::adoptElementType( ::capnp::Orphan< ::capnp::schema::Type>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Type> Type::List::Builder::disownElementType() { return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint64_t Type::Enum::Reader::getTypeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Type::Enum::Builder::getTypeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Type::Enum::Builder::setTypeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Type::Enum::Reader::hasBrand() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Type::Enum::Builder::hasBrand() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Type::Enum::Reader::getBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Type::Enum::Builder::getBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Type::Enum::Pipeline::getBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Type::Enum::Builder::setBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Type::Enum::Builder::initBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Type::Enum::Builder::adoptBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Enum::Builder::disownBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint64_t Type::Struct::Reader::getTypeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Type::Struct::Builder::getTypeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Type::Struct::Builder::setTypeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Type::Struct::Reader::hasBrand() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Type::Struct::Builder::hasBrand() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Type::Struct::Reader::getBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Type::Struct::Builder::getBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Type::Struct::Pipeline::getBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Type::Struct::Builder::setBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Type::Struct::Builder::initBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Type::Struct::Builder::adoptBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Struct::Builder::disownBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint64_t Type::Interface::Reader::getTypeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Type::Interface::Builder::getTypeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Type::Interface::Builder::setTypeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Type::Interface::Reader::hasBrand() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Type::Interface::Builder::hasBrand() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Type::Interface::Reader::getBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Type::Interface::Builder::getBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Type::Interface::Pipeline::getBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Type::Interface::Builder::setBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Type::Interface::Builder::initBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Type::Interface::Builder::adoptBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Type::Interface::Builder::disownBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::AnyPointer::Which Type::AnyPointer::Reader::which() const { return _reader.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Type::AnyPointer::Which Type::AnyPointer::Builder::which() { return _builder.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline bool Type::AnyPointer::Reader::isUnconstrained() const { return which() == Type::AnyPointer::UNCONSTRAINED; } inline bool Type::AnyPointer::Builder::isUnconstrained() { return which() == Type::AnyPointer::UNCONSTRAINED; } inline typename Type::AnyPointer::Unconstrained::Reader Type::AnyPointer::Reader::getUnconstrained() const { KJ_IREQUIRE((which() == Type::AnyPointer::UNCONSTRAINED), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Unconstrained::Reader(_reader); } inline typename Type::AnyPointer::Unconstrained::Builder Type::AnyPointer::Builder::getUnconstrained() { KJ_IREQUIRE((which() == Type::AnyPointer::UNCONSTRAINED), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Unconstrained::Builder(_builder); } inline typename Type::AnyPointer::Unconstrained::Builder Type::AnyPointer::Builder::initUnconstrained() { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::UNCONSTRAINED); _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); return typename Type::AnyPointer::Unconstrained::Builder(_builder); } inline bool Type::AnyPointer::Reader::isParameter() const { return which() == Type::AnyPointer::PARAMETER; } inline bool Type::AnyPointer::Builder::isParameter() { return which() == Type::AnyPointer::PARAMETER; } inline typename Type::AnyPointer::Parameter::Reader Type::AnyPointer::Reader::getParameter() const { KJ_IREQUIRE((which() == Type::AnyPointer::PARAMETER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Parameter::Reader(_reader); } inline typename Type::AnyPointer::Parameter::Builder Type::AnyPointer::Builder::getParameter() { KJ_IREQUIRE((which() == Type::AnyPointer::PARAMETER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::Parameter::Builder(_builder); } inline typename Type::AnyPointer::Parameter::Builder Type::AnyPointer::Builder::initParameter() { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::PARAMETER); _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint64_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); return typename Type::AnyPointer::Parameter::Builder(_builder); } inline bool Type::AnyPointer::Reader::isImplicitMethodParameter() const { return which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER; } inline bool Type::AnyPointer::Builder::isImplicitMethodParameter() { return which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER; } inline typename Type::AnyPointer::ImplicitMethodParameter::Reader Type::AnyPointer::Reader::getImplicitMethodParameter() const { KJ_IREQUIRE((which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::ImplicitMethodParameter::Reader(_reader); } inline typename Type::AnyPointer::ImplicitMethodParameter::Builder Type::AnyPointer::Builder::getImplicitMethodParameter() { KJ_IREQUIRE((which() == Type::AnyPointer::IMPLICIT_METHOD_PARAMETER), "Must check which() before get()ing a union member."); return typename Type::AnyPointer::ImplicitMethodParameter::Builder(_builder); } inline typename Type::AnyPointer::ImplicitMethodParameter::Builder Type::AnyPointer::Builder::initImplicitMethodParameter() { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Type::AnyPointer::IMPLICIT_METHOD_PARAMETER); _builder.setDataField< ::uint16_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0); return typename Type::AnyPointer::ImplicitMethodParameter::Builder(_builder); } inline ::capnp::schema::Type::AnyPointer::Unconstrained::Which Type::AnyPointer::Unconstrained::Reader::which() const { return _reader.getDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Type::AnyPointer::Unconstrained::Which Type::AnyPointer::Unconstrained::Builder::which() { return _builder.getDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline bool Type::AnyPointer::Unconstrained::Reader::isAnyKind() const { return which() == Type::AnyPointer::Unconstrained::ANY_KIND; } inline bool Type::AnyPointer::Unconstrained::Builder::isAnyKind() { return which() == Type::AnyPointer::Unconstrained::ANY_KIND; } inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getAnyKind() const { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::ANY_KIND), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getAnyKind() { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::ANY_KIND), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Unconstrained::Builder::setAnyKind( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::ANY_KIND); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::AnyPointer::Unconstrained::Reader::isStruct() const { return which() == Type::AnyPointer::Unconstrained::STRUCT; } inline bool Type::AnyPointer::Unconstrained::Builder::isStruct() { return which() == Type::AnyPointer::Unconstrained::STRUCT; } inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getStruct() const { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::STRUCT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getStruct() { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::STRUCT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Unconstrained::Builder::setStruct( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::STRUCT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::AnyPointer::Unconstrained::Reader::isList() const { return which() == Type::AnyPointer::Unconstrained::LIST; } inline bool Type::AnyPointer::Unconstrained::Builder::isList() { return which() == Type::AnyPointer::Unconstrained::LIST; } inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getList() const { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::LIST), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getList() { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::LIST), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Unconstrained::Builder::setList( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::LIST); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Type::AnyPointer::Unconstrained::Reader::isCapability() const { return which() == Type::AnyPointer::Unconstrained::CAPABILITY; } inline bool Type::AnyPointer::Unconstrained::Builder::isCapability() { return which() == Type::AnyPointer::Unconstrained::CAPABILITY; } inline ::capnp::Void Type::AnyPointer::Unconstrained::Reader::getCapability() const { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::CAPABILITY), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Type::AnyPointer::Unconstrained::Builder::getCapability() { KJ_IREQUIRE((which() == Type::AnyPointer::Unconstrained::CAPABILITY), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Unconstrained::Builder::setCapability( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<5>() * ::capnp::ELEMENTS, Type::AnyPointer::Unconstrained::CAPABILITY); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint64_t Type::AnyPointer::Parameter::Reader::getScopeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint64_t Type::AnyPointer::Parameter::Builder::getScopeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Parameter::Builder::setScopeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Type::AnyPointer::Parameter::Reader::getParameterIndex() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline ::uint16_t Type::AnyPointer::Parameter::Builder::getParameterIndex() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::Parameter::Builder::setParameterIndex( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Type::AnyPointer::ImplicitMethodParameter::Reader::getParameterIndex() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline ::uint16_t Type::AnyPointer::ImplicitMethodParameter::Builder::getParameterIndex() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS); } inline void Type::AnyPointer::ImplicitMethodParameter::Builder::setParameterIndex( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<5>() * ::capnp::ELEMENTS, value); } inline bool Brand::Reader::hasScopes() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Brand::Builder::hasScopes() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader Brand::Reader::getScopes() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder Brand::Builder::getScopes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Brand::Builder::setScopes( ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>::Builder Brand::Builder::initScopes(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Brand::Builder::adoptScopes( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>> Brand::Builder::disownScopes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Scope, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Scope::Which Brand::Scope::Reader::which() const { return _reader.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Brand::Scope::Which Brand::Scope::Builder::which() { return _builder.getDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS); } inline ::uint64_t Brand::Scope::Reader::getScopeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Brand::Scope::Builder::getScopeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Brand::Scope::Builder::setScopeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Brand::Scope::Reader::isBind() const { return which() == Brand::Scope::BIND; } inline bool Brand::Scope::Builder::isBind() { return which() == Brand::Scope::BIND; } inline bool Brand::Scope::Reader::hasBind() const { if (which() != Brand::Scope::BIND) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Brand::Scope::Builder::hasBind() { if (which() != Brand::Scope::BIND) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader Brand::Scope::Reader::getBind() const { KJ_IREQUIRE((which() == Brand::Scope::BIND), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder Brand::Scope::Builder::getBind() { KJ_IREQUIRE((which() == Brand::Scope::BIND), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Brand::Scope::Builder::setBind( ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>::Builder Brand::Scope::Builder::initBind(unsigned int size) { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Brand::Scope::Builder::adoptBind( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::BIND); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>> Brand::Scope::Builder::disownBind() { KJ_IREQUIRE((which() == Brand::Scope::BIND), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Brand::Binding, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Brand::Scope::Reader::isInherit() const { return which() == Brand::Scope::INHERIT; } inline bool Brand::Scope::Builder::isInherit() { return which() == Brand::Scope::INHERIT; } inline ::capnp::Void Brand::Scope::Reader::getInherit() const { KJ_IREQUIRE((which() == Brand::Scope::INHERIT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Brand::Scope::Builder::getInherit() { KJ_IREQUIRE((which() == Brand::Scope::INHERIT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Brand::Scope::Builder::setInherit( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<4>() * ::capnp::ELEMENTS, Brand::Scope::INHERIT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::capnp::schema::Brand::Binding::Which Brand::Binding::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Brand::Binding::Which Brand::Binding::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Brand::Binding::Reader::isUnbound() const { return which() == Brand::Binding::UNBOUND; } inline bool Brand::Binding::Builder::isUnbound() { return which() == Brand::Binding::UNBOUND; } inline ::capnp::Void Brand::Binding::Reader::getUnbound() const { KJ_IREQUIRE((which() == Brand::Binding::UNBOUND), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Brand::Binding::Builder::getUnbound() { KJ_IREQUIRE((which() == Brand::Binding::UNBOUND), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Brand::Binding::Builder::setUnbound( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::UNBOUND); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Brand::Binding::Reader::isType() const { return which() == Brand::Binding::TYPE; } inline bool Brand::Binding::Builder::isType() { return which() == Brand::Binding::TYPE; } inline bool Brand::Binding::Reader::hasType() const { if (which() != Brand::Binding::TYPE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Brand::Binding::Builder::hasType() { if (which() != Brand::Binding::TYPE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Type::Reader Brand::Binding::Reader::getType() const { KJ_IREQUIRE((which() == Brand::Binding::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Type::Builder Brand::Binding::Builder::getType() { KJ_IREQUIRE((which() == Brand::Binding::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Brand::Binding::Builder::setType( ::capnp::schema::Type::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); ::capnp::_::PointerHelpers< ::capnp::schema::Type>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Type::Builder Brand::Binding::Builder::initType() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Brand::Binding::Builder::adoptType( ::capnp::Orphan< ::capnp::schema::Type>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Brand::Binding::TYPE); ::capnp::_::PointerHelpers< ::capnp::schema::Type>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Type> Brand::Binding::Builder::disownType() { KJ_IREQUIRE((which() == Brand::Binding::TYPE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::schema::Type>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Value::Which Value::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::schema::Value::Which Value::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Value::Reader::isVoid() const { return which() == Value::VOID; } inline bool Value::Builder::isVoid() { return which() == Value::VOID; } inline ::capnp::Void Value::Reader::getVoid() const { KJ_IREQUIRE((which() == Value::VOID), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Value::Builder::getVoid() { KJ_IREQUIRE((which() == Value::VOID), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Value::Builder::setVoid( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::VOID); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isBool() const { return which() == Value::BOOL; } inline bool Value::Builder::isBool() { return which() == Value::BOOL; } inline bool Value::Reader::getBool() const { KJ_IREQUIRE((which() == Value::BOOL), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS); } inline bool Value::Builder::getBool() { KJ_IREQUIRE((which() == Value::BOOL), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS); } inline void Value::Builder::setBool(bool value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::BOOL); _builder.setDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isInt8() const { return which() == Value::INT8; } inline bool Value::Builder::isInt8() { return which() == Value::INT8; } inline ::int8_t Value::Reader::getInt8() const { KJ_IREQUIRE((which() == Value::INT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::int8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::int8_t Value::Builder::getInt8() { KJ_IREQUIRE((which() == Value::INT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::int8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Value::Builder::setInt8( ::int8_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT8); _builder.setDataField< ::int8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isInt16() const { return which() == Value::INT16; } inline bool Value::Builder::isInt16() { return which() == Value::INT16; } inline ::int16_t Value::Reader::getInt16() const { KJ_IREQUIRE((which() == Value::INT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::int16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::int16_t Value::Builder::getInt16() { KJ_IREQUIRE((which() == Value::INT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::int16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setInt16( ::int16_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT16); _builder.setDataField< ::int16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isInt32() const { return which() == Value::INT32; } inline bool Value::Builder::isInt32() { return which() == Value::INT32; } inline ::int32_t Value::Reader::getInt32() const { KJ_IREQUIRE((which() == Value::INT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::int32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::int32_t Value::Builder::getInt32() { KJ_IREQUIRE((which() == Value::INT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::int32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setInt32( ::int32_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT32); _builder.setDataField< ::int32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isInt64() const { return which() == Value::INT64; } inline bool Value::Builder::isInt64() { return which() == Value::INT64; } inline ::int64_t Value::Reader::getInt64() const { KJ_IREQUIRE((which() == Value::INT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::int64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::int64_t Value::Builder::getInt64() { KJ_IREQUIRE((which() == Value::INT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::int64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setInt64( ::int64_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INT64); _builder.setDataField< ::int64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isUint8() const { return which() == Value::UINT8; } inline bool Value::Builder::isUint8() { return which() == Value::UINT8; } inline ::uint8_t Value::Reader::getUint8() const { KJ_IREQUIRE((which() == Value::UINT8), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint8_t Value::Builder::getUint8() { KJ_IREQUIRE((which() == Value::UINT8), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Value::Builder::setUint8( ::uint8_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT8); _builder.setDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isUint16() const { return which() == Value::UINT16; } inline bool Value::Builder::isUint16() { return which() == Value::UINT16; } inline ::uint16_t Value::Reader::getUint16() const { KJ_IREQUIRE((which() == Value::UINT16), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint16_t Value::Builder::getUint16() { KJ_IREQUIRE((which() == Value::UINT16), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setUint16( ::uint16_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT16); _builder.setDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isUint32() const { return which() == Value::UINT32; } inline bool Value::Builder::isUint32() { return which() == Value::UINT32; } inline ::uint32_t Value::Reader::getUint32() const { KJ_IREQUIRE((which() == Value::UINT32), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Value::Builder::getUint32() { KJ_IREQUIRE((which() == Value::UINT32), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setUint32( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT32); _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isUint64() const { return which() == Value::UINT64; } inline bool Value::Builder::isUint64() { return which() == Value::UINT64; } inline ::uint64_t Value::Reader::getUint64() const { KJ_IREQUIRE((which() == Value::UINT64), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Value::Builder::getUint64() { KJ_IREQUIRE((which() == Value::UINT64), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setUint64( ::uint64_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::UINT64); _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isFloat32() const { return which() == Value::FLOAT32; } inline bool Value::Builder::isFloat32() { return which() == Value::FLOAT32; } inline float Value::Reader::getFloat32() const { KJ_IREQUIRE((which() == Value::FLOAT32), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline float Value::Builder::getFloat32() { KJ_IREQUIRE((which() == Value::FLOAT32), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setFloat32(float value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::FLOAT32); _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isFloat64() const { return which() == Value::FLOAT64; } inline bool Value::Builder::isFloat64() { return which() == Value::FLOAT64; } inline double Value::Reader::getFloat64() const { KJ_IREQUIRE((which() == Value::FLOAT64), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline double Value::Builder::getFloat64() { KJ_IREQUIRE((which() == Value::FLOAT64), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setFloat64(double value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::FLOAT64); _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isText() const { return which() == Value::TEXT; } inline bool Value::Builder::isText() { return which() == Value::TEXT; } inline bool Value::Reader::hasText() const { if (which() != Value::TEXT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasText() { if (which() != Value::TEXT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Value::Reader::getText() const { KJ_IREQUIRE((which() == Value::TEXT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Value::Builder::getText() { KJ_IREQUIRE((which() == Value::TEXT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setText( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Value::Builder::initText(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptText( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::TEXT); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Value::Builder::disownText() { KJ_IREQUIRE((which() == Value::TEXT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isData() const { return which() == Value::DATA; } inline bool Value::Builder::isData() { return which() == Value::DATA; } inline bool Value::Reader::hasData() const { if (which() != Value::DATA) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasData() { if (which() != Value::DATA) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Data::Reader Value::Reader::getData() const { KJ_IREQUIRE((which() == Value::DATA), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Data::Builder Value::Builder::getData() { KJ_IREQUIRE((which() == Value::DATA), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setData( ::capnp::Data::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); ::capnp::_::PointerHelpers< ::capnp::Data>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Data::Builder Value::Builder::initData(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); return ::capnp::_::PointerHelpers< ::capnp::Data>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptData( ::capnp::Orphan< ::capnp::Data>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::DATA); ::capnp::_::PointerHelpers< ::capnp::Data>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Data> Value::Builder::disownData() { KJ_IREQUIRE((which() == Value::DATA), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Data>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isList() const { return which() == Value::LIST; } inline bool Value::Builder::isList() { return which() == Value::LIST; } inline bool Value::Reader::hasList() const { if (which() != Value::LIST) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasList() { if (which() != Value::LIST) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Value::Reader::getList() const { KJ_IREQUIRE((which() == Value::LIST), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::getList() { KJ_IREQUIRE((which() == Value::LIST), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::initList() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::LIST); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Value::Reader::isEnum() const { return which() == Value::ENUM; } inline bool Value::Builder::isEnum() { return which() == Value::ENUM; } inline ::uint16_t Value::Reader::getEnum() const { KJ_IREQUIRE((which() == Value::ENUM), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint16_t Value::Builder::getEnum() { KJ_IREQUIRE((which() == Value::ENUM), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setEnum( ::uint16_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ENUM); _builder.setDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isStruct() const { return which() == Value::STRUCT; } inline bool Value::Builder::isStruct() { return which() == Value::STRUCT; } inline bool Value::Reader::hasStruct() const { if (which() != Value::STRUCT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasStruct() { if (which() != Value::STRUCT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Value::Reader::getStruct() const { KJ_IREQUIRE((which() == Value::STRUCT), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::getStruct() { KJ_IREQUIRE((which() == Value::STRUCT), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::initStruct() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::STRUCT); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Value::Reader::isInterface() const { return which() == Value::INTERFACE; } inline bool Value::Builder::isInterface() { return which() == Value::INTERFACE; } inline ::capnp::Void Value::Reader::getInterface() const { KJ_IREQUIRE((which() == Value::INTERFACE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Value::Builder::getInterface() { KJ_IREQUIRE((which() == Value::INTERFACE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Value::Builder::setInterface( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::INTERFACE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isAnyPointer() const { return which() == Value::ANY_POINTER; } inline bool Value::Builder::isAnyPointer() { return which() == Value::ANY_POINTER; } inline bool Value::Reader::hasAnyPointer() const { if (which() != Value::ANY_POINTER) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasAnyPointer() { if (which() != Value::ANY_POINTER) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Value::Reader::getAnyPointer() const { KJ_IREQUIRE((which() == Value::ANY_POINTER), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::getAnyPointer() { KJ_IREQUIRE((which() == Value::ANY_POINTER), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Value::Builder::initAnyPointer() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ANY_POINTER); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::uint64_t Annotation::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t Annotation::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Annotation::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Annotation::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Annotation::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Value::Reader Annotation::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::Value::Builder Annotation::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Value::Pipeline Annotation::Pipeline::getValue() { return ::capnp::schema::Value::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Annotation::Builder::setValue( ::capnp::schema::Value::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Value::Builder Annotation::Builder::initValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Annotation::Builder::adoptValue( ::capnp::Orphan< ::capnp::schema::Value>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Value>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Value> Annotation::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::schema::Value>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Annotation::Reader::hasBrand() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Annotation::Builder::hasBrand() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::Brand::Reader Annotation::Reader::getBrand() const { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::schema::Brand::Builder Annotation::Builder::getBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::Brand::Pipeline Annotation::Pipeline::getBrand() { return ::capnp::schema::Brand::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Annotation::Builder::setBrand( ::capnp::schema::Brand::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::schema::Brand::Builder Annotation::Builder::initBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Annotation::Builder::adoptBrand( ::capnp::Orphan< ::capnp::schema::Brand>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::Brand> Annotation::Builder::disownBrand() { return ::capnp::_::PointerHelpers< ::capnp::schema::Brand>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::uint16_t CapnpVersion::Reader::getMajor() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint16_t CapnpVersion::Builder::getMajor() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void CapnpVersion::Builder::setMajor( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint8_t CapnpVersion::Reader::getMinor() const { return _reader.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint8_t CapnpVersion::Builder::getMinor() { return _builder.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void CapnpVersion::Builder::setMinor( ::uint8_t value) { _builder.setDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline ::uint8_t CapnpVersion::Reader::getMicro() const { return _reader.getDataField< ::uint8_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint8_t CapnpVersion::Builder::getMicro() { return _builder.getDataField< ::uint8_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline void CapnpVersion::Builder::setMicro( ::uint8_t value) { _builder.setDataField< ::uint8_t>( ::capnp::bounded<3>() * ::capnp::ELEMENTS, value); } inline bool CodeGeneratorRequest::Reader::hasNodes() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::Builder::hasNodes() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Reader CodeGeneratorRequest::Reader::getNodes() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::getNodes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::Builder::setNodes( ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::initNodes(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::Builder::adoptNodes( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>> CodeGeneratorRequest::Builder::disownNodes() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::Reader::hasRequestedFiles() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::Builder::hasRequestedFiles() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Reader CodeGeneratorRequest::Reader::getRequestedFiles() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::getRequestedFiles() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::Builder::setRequestedFiles( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::initRequestedFiles(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::Builder::adoptRequestedFiles( ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>> CodeGeneratorRequest::Builder::disownRequestedFiles() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::Reader::hasCapnpVersion() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::Builder::hasCapnpVersion() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::CapnpVersion::Reader CodeGeneratorRequest::Reader::getCapnpVersion() const { return ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::schema::CapnpVersion::Builder CodeGeneratorRequest::Builder::getCapnpVersion() { return ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::CapnpVersion::Pipeline CodeGeneratorRequest::Pipeline::getCapnpVersion() { return ::capnp::schema::CapnpVersion::Pipeline(_typeless.getPointerField(2)); } #endif // !CAPNP_LITE inline void CodeGeneratorRequest::Builder::setCapnpVersion( ::capnp::schema::CapnpVersion::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::schema::CapnpVersion::Builder CodeGeneratorRequest::Builder::initCapnpVersion() { return ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::Builder::adoptCapnpVersion( ::capnp::Orphan< ::capnp::schema::CapnpVersion>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::CapnpVersion> CodeGeneratorRequest::Builder::disownCapnpVersion() { return ::capnp::_::PointerHelpers< ::capnp::schema::CapnpVersion>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::Reader::hasSourceInfo() const { return !_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::Builder::hasSourceInfo() { return !_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Reader CodeGeneratorRequest::Reader::getSourceInfo() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::getSourceInfo() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::Builder::setSourceInfo( ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::Builder::initSourceInfo(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::Builder::adoptSourceInfo( ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>> CodeGeneratorRequest::Builder::disownSourceInfo() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::Node::SourceInfo, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<3>() * ::capnp::POINTERS)); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool CodeGeneratorRequest::RequestedFile::Reader::hasFilename() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::RequestedFile::Builder::hasFilename() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader CodeGeneratorRequest::RequestedFile::Reader::getFilename() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder CodeGeneratorRequest::RequestedFile::Builder::getFilename() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::RequestedFile::Builder::setFilename( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder CodeGeneratorRequest::RequestedFile::Builder::initFilename(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::RequestedFile::Builder::adoptFilename( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> CodeGeneratorRequest::RequestedFile::Builder::disownFilename() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::RequestedFile::Reader::hasImports() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::RequestedFile::Builder::hasImports() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Reader CodeGeneratorRequest::RequestedFile::Reader::getImports() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::RequestedFile::Builder::getImports() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::RequestedFile::Builder::setImports( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::RequestedFile::Builder::initImports(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::RequestedFile::Builder::adoptImports( ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>> CodeGeneratorRequest::RequestedFile::Builder::disownImports() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::Import, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::RequestedFile::Reader::hasFileSourceInfo() const { return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::RequestedFile::Builder::hasFileSourceInfo() { return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader CodeGeneratorRequest::RequestedFile::Reader::getFileSourceInfo() const { return ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::get(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder CodeGeneratorRequest::RequestedFile::Builder::getFileSourceInfo() { return ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::get(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Pipeline CodeGeneratorRequest::RequestedFile::Pipeline::getFileSourceInfo() { return ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Pipeline(_typeless.getPointerField(2)); } #endif // !CAPNP_LITE inline void CodeGeneratorRequest::RequestedFile::Builder::setFileSourceInfo( ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader value) { ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::set(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), value); } inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder CodeGeneratorRequest::RequestedFile::Builder::initFileSourceInfo() { return ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::init(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::RequestedFile::Builder::adoptFileSourceInfo( ::capnp::Orphan< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>&& value) { ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::adopt(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo> CodeGeneratorRequest::RequestedFile::Builder::disownFileSourceInfo() { return ::capnp::_::PointerHelpers< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo>::disown(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::Import::Reader::getId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::Import::Builder::getId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::Import::Builder::setId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool CodeGeneratorRequest::RequestedFile::Import::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::RequestedFile::Import::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader CodeGeneratorRequest::RequestedFile::Import::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder CodeGeneratorRequest::RequestedFile::Import::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::RequestedFile::Import::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder CodeGeneratorRequest::RequestedFile::Import::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::RequestedFile::Import::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> CodeGeneratorRequest::RequestedFile::Import::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader::hasIdentifiers() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::hasIdentifiers() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Reader CodeGeneratorRequest::RequestedFile::FileSourceInfo::Reader::getIdentifiers() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::getIdentifiers() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::setIdentifiers( ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>::Builder CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::initIdentifiers(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::adoptIdentifiers( ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>> CodeGeneratorRequest::RequestedFile::FileSourceInfo::Builder::disownIdentifiers() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Which CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::which() const { return _reader.getDataField( ::capnp::bounded<8>() * ::capnp::ELEMENTS); } inline ::capnp::schema::CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Which CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::which() { return _builder.getDataField( ::capnp::bounded<8>() * ::capnp::ELEMENTS); } inline ::uint32_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::getStartByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::getStartByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::setStartByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::getEndByte() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::getEndByte() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::setEndByte( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::isTypeId() const { return which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::TYPE_ID; } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::isTypeId() { return which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::TYPE_ID; } inline ::uint64_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::getTypeId() const { KJ_IREQUIRE((which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::TYPE_ID), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::getTypeId() { KJ_IREQUIRE((which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::TYPE_ID), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::setTypeId( ::uint64_t value) { _builder.setDataField( ::capnp::bounded<8>() * ::capnp::ELEMENTS, CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::TYPE_ID); _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::isMember() const { return which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::MEMBER; } inline bool CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::isMember() { return which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::MEMBER; } inline typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Reader CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Reader::getMember() const { KJ_IREQUIRE((which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::MEMBER), "Must check which() before get()ing a union member."); return typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Reader(_reader); } inline typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::getMember() { KJ_IREQUIRE((which() == CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::MEMBER), "Must check which() before get()ing a union member."); return typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder(_builder); } inline typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Builder::initMember() { _builder.setDataField( ::capnp::bounded<8>() * ::capnp::ELEMENTS, CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::MEMBER); _builder.setDataField< ::uint64_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<9>() * ::capnp::ELEMENTS, 0); return typename CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder(_builder); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Reader::getParentTypeId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder::getParentTypeId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder::setParentTypeId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Reader::getOrdinal() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<9>() * ::capnp::ELEMENTS); } inline ::uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder::getOrdinal() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<9>() * ::capnp::ELEMENTS); } inline void CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::Builder::setOrdinal( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<9>() * ::capnp::ELEMENTS, value); } } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/stringify.c++0000644000175000017500000002261214712011043021136 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "dynamic.h" #include #include #include namespace capnp { namespace { enum PrintMode { BARE, // The value is planned to be printed on its own line, unless it is very short and contains // no inner newlines. PREFIXED, // The value is planned to be printed with a prefix, like "memberName = " (a struct field). PARENTHESIZED // The value is printed in parenthesized (a union value). }; enum class PrintKind { LIST, RECORD }; class Indent { public: explicit Indent(bool enable): amount(enable ? 1 : 0) {} Indent next() { return Indent(amount == 0 ? 0 : amount + 1); } kj::StringTree delimit(kj::Array items, PrintMode mode, PrintKind kind) { if (amount == 0 || canPrintAllInline(items, kind)) { return kj::StringTree(kj::mv(items), ", "); } else { KJ_STACK_ARRAY(char, delimArrayPtr, amount * 2 + 3, 32, 256); auto delim = delimArrayPtr.begin(); delim[0] = ','; delim[1] = '\n'; memset(delim + 2, ' ', amount * 2); delim[amount * 2 + 2] = '\0'; // If the outer value isn't being printed on its own line, we need to add a newline/indent // before the first item, otherwise we only add a space on the assumption that it is preceded // by an open bracket or parenthesis. return kj::strTree(mode == BARE ? " " : delim + 1, kj::StringTree(kj::mv(items), kj::StringPtr(delim, amount * 2 + 2)), ' '); } } private: uint amount; explicit Indent(uint amount): amount(amount) {} static constexpr size_t maxInlineValueSize = 24; static constexpr size_t maxInlineRecordSize = 64; static bool canPrintInline(const kj::StringTree& text) { if (text.size() > maxInlineValueSize) { return false; } char flat[maxInlineValueSize + 1]; text.flattenTo(flat); flat[text.size()] = '\0'; if (strchr(flat, '\n') != nullptr) { return false; } return true; } static bool canPrintAllInline(const kj::Array& items, PrintKind kind) { size_t totalSize = 0; for (auto& item: items) { if (!canPrintInline(item)) return false; if (kind == PrintKind::RECORD) { totalSize += item.size(); if (totalSize > maxInlineRecordSize) return false; } } return true; } }; static schema::Type::Which whichFieldType(const StructSchema::Field& field) { auto proto = field.getProto(); switch (proto.which()) { case schema::Field::SLOT: return proto.getSlot().getType().which(); case schema::Field::GROUP: return schema::Type::STRUCT; } KJ_UNREACHABLE; } static kj::StringTree print(const DynamicValue::Reader& value, schema::Type::Which which, Indent indent, PrintMode mode) { switch (value.getType()) { case DynamicValue::UNKNOWN: return kj::strTree("?"); case DynamicValue::VOID: return kj::strTree("void"); case DynamicValue::BOOL: return kj::strTree(value.as() ? "true" : "false"); case DynamicValue::INT: return kj::strTree(value.as()); case DynamicValue::UINT: return kj::strTree(value.as()); case DynamicValue::FLOAT: if (which == schema::Type::FLOAT32) { return kj::strTree(value.as()); } else { return kj::strTree(value.as()); } case DynamicValue::TEXT: { kj::ArrayPtr chars = value.as(); return kj::strTree('"', kj::encodeCEscape(chars), '"'); } case DynamicValue::DATA: { // TODO(someday): Maybe data should be printed as binary literal. kj::ArrayPtr bytes = value.as().asBytes(); return kj::strTree('"', kj::encodeCEscape(bytes), '"'); } case DynamicValue::LIST: { auto listValue = value.as(); auto which = listValue.getSchema().whichElementType(); kj::Array elements = KJ_MAP(element, listValue) { return print(element, which, indent.next(), BARE); }; return kj::strTree('[', indent.delimit(kj::mv(elements), mode, PrintKind::LIST), ']'); } case DynamicValue::ENUM: { auto enumValue = value.as(); KJ_IF_MAYBE(enumerant, enumValue.getEnumerant()) { return kj::strTree(enumerant->getProto().getName()); } else { // Unknown enum value; output raw number. return kj::strTree('(', enumValue.getRaw(), ')'); } break; } case DynamicValue::STRUCT: { auto structValue = value.as(); auto unionFields = structValue.getSchema().getUnionFields(); auto nonUnionFields = structValue.getSchema().getNonUnionFields(); kj::Vector printedFields(nonUnionFields.size() + (unionFields.size() != 0)); // We try to write the union field, if any, in proper order with the rest. auto which = structValue.which(); kj::StringTree unionValue; KJ_IF_MAYBE(field, which) { // Even if the union field has its default value, if it is not the default field of the // union then we have to print it anyway. auto fieldProto = field->getProto(); if (fieldProto.getDiscriminantValue() != 0 || structValue.has(*field)) { unionValue = kj::strTree( fieldProto.getName(), " = ", print(structValue.get(*field), whichFieldType(*field), indent.next(), PREFIXED)); } else { which = nullptr; } } for (auto field: nonUnionFields) { KJ_IF_MAYBE(unionField, which) { if (unionField->getIndex() < field.getIndex()) { printedFields.add(kj::mv(unionValue)); which = nullptr; } } if (structValue.has(field)) { printedFields.add(kj::strTree( field.getProto().getName(), " = ", print(structValue.get(field), whichFieldType(field), indent.next(), PREFIXED))); } } if (which != nullptr) { // Union value is last. printedFields.add(kj::mv(unionValue)); } if (mode == PARENTHESIZED) { return indent.delimit(printedFields.releaseAsArray(), mode, PrintKind::RECORD); } else { return kj::strTree( '(', indent.delimit(printedFields.releaseAsArray(), mode, PrintKind::RECORD), ')'); } } case DynamicValue::CAPABILITY: return kj::strTree(""); case DynamicValue::ANY_POINTER: return kj::strTree(""); } KJ_UNREACHABLE; } kj::StringTree stringify(DynamicValue::Reader value) { return print(value, schema::Type::STRUCT, Indent(false), BARE); } } // namespace kj::StringTree prettyPrint(DynamicStruct::Reader value) { return print(value, schema::Type::STRUCT, Indent(true), BARE); } kj::StringTree prettyPrint(DynamicList::Reader value) { return print(value, schema::Type::LIST, Indent(true), BARE); } kj::StringTree prettyPrint(DynamicStruct::Builder value) { return prettyPrint(value.asReader()); } kj::StringTree prettyPrint(DynamicList::Builder value) { return prettyPrint(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value) { return stringify(value.asReader()); } namespace _ { // private kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema) { return stringify(DynamicStruct::Reader(Schema(&schema).asStruct(), reader)); } kj::String enumString(uint16_t value, const RawBrandedSchema& schema) { auto enumerants = Schema(&schema).asEnum().getEnumerants(); if (value < enumerants.size()) { return kj::heapString(enumerants[value].getProto().getName()); } else { return kj::str(value); } } } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/arena.c++0000644000175000017500000003416414712011043020213 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "arena.h" #include "message.h" #include #include #include #include #include #include #if !CAPNP_LITE #include "capability.h" #endif // !CAPNP_LITE namespace capnp { namespace _ { // private Arena::~Arena() noexcept(false) {} void ReadLimiter::unread(WordCount64 amount) { // Be careful not to overflow here. Since ReadLimiter has no thread-safety, it's possible that // the limit value was not updated correctly for one or more reads, and therefore unread() could // overflow it even if it is only unreading bytes that were actually read. uint64_t oldValue = readLimit(); uint64_t newValue = oldValue + unbound(amount / WORDS); if (newValue > oldValue) { setLimit(newValue); } } void SegmentReader::abortCheckObjectFault() { KJ_LOG(FATAL, "checkObject()'s parameter is not in-range; this would segfault in opt mode", "this is a serious bug in Cap'n Proto; please notify security@sandstorm.io"); abort(); } void SegmentBuilder::throwNotWritable() { KJ_FAIL_REQUIRE( "Tried to form a Builder to an external data segment referenced by the MessageBuilder. " "When you use Orphanage::reference*(), you are not allowed to obtain Builders to the " "referenced data, only Readers, because that data is const."); } // ======================================================================================= static SegmentWordCount verifySegmentSize(size_t size) { auto gsize = bounded(size) * WORDS; return assertMaxBits(gsize, [&]() { KJ_FAIL_REQUIRE("segment is too large", size); }); } static SegmentWordCount verifySegment(kj::ArrayPtr segment) { #if !CAPNP_ALLOW_UNALIGNED KJ_REQUIRE(reinterpret_cast(segment.begin()) % sizeof(void*) == 0, "Detected unaligned data in Cap'n Proto message. Messages must be aligned to the " "architecture's word size. Yes, even on x86: Unaligned access is undefined behavior " "under the C/C++ language standard, and compilers can and do assume alignment for the " "purpose of optimizations. Unaligned access may lead to crashes or subtle corruption. " "For example, GCC will use SIMD instructions in optimizations, and those instrsuctions " "require alignment. If you really insist on taking your changes with unaligned data, " "compile the Cap'n Proto library with -DCAPNP_ALLOW_UNALIGNED to remove this check.") { break; } #endif return verifySegmentSize(segment.size()); } inline ReaderArena::ReaderArena(MessageReader* message, const word* firstSegment, SegmentWordCount firstSegmentSize) : message(message), readLimiter(bounded(message->getOptions().traversalLimitInWords) * WORDS), segment0(this, SegmentId(0), firstSegment, firstSegmentSize, &readLimiter) {} inline ReaderArena::ReaderArena(MessageReader* message, kj::ArrayPtr firstSegment) : ReaderArena(message, firstSegment.begin(), verifySegment(firstSegment)) {} ReaderArena::ReaderArena(MessageReader* message) : ReaderArena(message, message->getSegment(0)) {} ReaderArena::~ReaderArena() noexcept(false) {} size_t ReaderArena::sizeInWords() { size_t total = segment0.getArray().size(); for (uint i = 1; ; i++) { SegmentReader* segment = tryGetSegment(SegmentId(i)); if (segment == nullptr) return total; total += unboundAs(segment->getSize() / WORDS); } } SegmentReader* ReaderArena::tryGetSegment(SegmentId id) { if (id == SegmentId(0)) { if (segment0.getArray() == nullptr) { return nullptr; } else { return &segment0; } } auto lock = moreSegments.lockExclusive(); SegmentMap* segments = nullptr; KJ_IF_MAYBE(s, *lock) { KJ_IF_MAYBE(segment, s->find(id.value)) { return *segment; } segments = s; } kj::ArrayPtr newSegment = message->getSegment(id.value); if (newSegment == nullptr) { return nullptr; } SegmentWordCount newSegmentSize = verifySegment(newSegment); if (*lock == nullptr) { // OK, the segment exists, so allocate the map. segments = &lock->emplace(); } auto segment = kj::heap( this, id, newSegment.begin(), newSegmentSize, &readLimiter); SegmentReader* result = segment; segments->insert(id.value, kj::mv(segment)); return result; } void ReaderArena::reportReadLimitReached() { KJ_FAIL_REQUIRE("Exceeded message traversal limit. See capnp::ReaderOptions.") { return; } } // ======================================================================================= BuilderArena::BuilderArena(MessageBuilder* message) : message(message), segment0(nullptr, SegmentId(0), nullptr, nullptr) {} BuilderArena::BuilderArena(MessageBuilder* message, kj::ArrayPtr segments) : message(message), segment0(this, SegmentId(0), segments[0].space.begin(), verifySegment(segments[0].space), &this->dummyLimiter, verifySegmentSize(segments[0].wordsUsed)) { if (segments.size() > 1) { kj::Vector> builders(segments.size() - 1); uint i = 1; for (auto& segment: segments.slice(1, segments.size())) { builders.add(kj::heap( this, SegmentId(i++), segment.space.begin(), verifySegment(segment.space), &this->dummyLimiter, verifySegmentSize(segment.wordsUsed))); } kj::Vector> forOutput; forOutput.resize(segments.size()); segmentWithSpace = builders.back(); this->moreSegments = kj::heap( MultiSegmentState { kj::mv(builders), kj::mv(forOutput) }); } else { segmentWithSpace = &segment0; } } BuilderArena::~BuilderArena() noexcept(false) {} size_t BuilderArena::sizeInWords() { KJ_IF_MAYBE(segmentState, moreSegments) { size_t total = segment0.currentlyAllocated().size(); for (auto& builder: segmentState->get()->builders) { total += builder->currentlyAllocated().size(); } return total; } else { if (segment0.getArena() == nullptr) { // We haven't actually allocated any segments yet. return 0; } else { // We have only one segment so far. return segment0.currentlyAllocated().size(); } } } SegmentBuilder* BuilderArena::getSegment(SegmentId id) { // This method is allowed to fail if the segment ID is not valid. if (id == SegmentId(0)) { return &segment0; } else { KJ_IF_MAYBE(s, moreSegments) { KJ_REQUIRE(id.value - 1 < s->get()->builders.size(), "invalid segment id", id.value); return const_cast(s->get()->builders[id.value - 1].get()); } else { KJ_FAIL_REQUIRE("invalid segment id", id.value); } } } BuilderArena::AllocateResult BuilderArena::allocate(SegmentWordCount amount) { if (segment0.getArena() == nullptr) { // We're allocating the first segment. kj::ArrayPtr ptr = message->allocateSegment(unbound(amount / WORDS)); auto actualSize = verifySegment(ptr); // Re-allocate segment0 in-place. This is a bit of a hack, but we have not returned any // pointers to this segment yet, so it should be fine. kj::dtor(segment0); kj::ctor(segment0, this, SegmentId(0), ptr.begin(), actualSize, &this->dummyLimiter); segmentWithSpace = &segment0; return AllocateResult { &segment0, segment0.allocate(amount) }; } else { if (segmentWithSpace != nullptr) { // Check if there is space in an existing segment. // TODO(perf): Check for available space in more than just the last segment. We don't // want this to be O(n), though, so we'll need to maintain some sort of table. Complicating // matters, we want SegmentBuilders::allocate() to be fast, so we can't update any such // table when allocation actually happens. Instead, we could have a priority queue based // on the last-known available size, and then re-check the size when we pop segments off it // and shove them to the back of the queue if they have become too small. word* attempt = segmentWithSpace->allocate(amount); if (attempt != nullptr) { return AllocateResult { segmentWithSpace, attempt }; } } // Need to allocate a new segment. SegmentBuilder* result = addSegmentInternal(message->allocateSegment(unbound(amount / WORDS))); // Check this new segment first the next time we need to allocate. segmentWithSpace = result; // Allocating from the new segment is guaranteed to succeed since we made it big enough. return AllocateResult { result, result->allocate(amount) }; } } SegmentBuilder* BuilderArena::addExternalSegment(kj::ArrayPtr content) { return addSegmentInternal(content); } template SegmentBuilder* BuilderArena::addSegmentInternal(kj::ArrayPtr content) { // This check should never fail in practice, since you can't get an Orphanage without allocating // the root segment. KJ_REQUIRE(segment0.getArena() != nullptr, "Can't allocate external segments before allocating the root segment."); auto contentSize = verifySegmentSize(content.size()); MultiSegmentState* segmentState; KJ_IF_MAYBE(s, moreSegments) { segmentState = *s; } else { auto newSegmentState = kj::heap(); segmentState = newSegmentState; moreSegments = kj::mv(newSegmentState); } kj::Own newBuilder = kj::heap( this, SegmentId(segmentState->builders.size() + 1), content.begin(), contentSize, &this->dummyLimiter); SegmentBuilder* result = newBuilder.get(); segmentState->builders.add(kj::mv(newBuilder)); // Keep forOutput the right size so that we don't have to re-allocate during // getSegmentsForOutput(), which callers might reasonably expect is a thread-safe method. segmentState->forOutput.resize(segmentState->builders.size() + 1); return result; } kj::ArrayPtr> BuilderArena::getSegmentsForOutput() { // Although this is a read-only method, we shouldn't need to lock a mutex here because if this // is called multiple times simultaneously, we should only be overwriting the array with the // exact same data. If the number or size of segments is actually changing due to an activity // in another thread, then the caller has a problem regardless of locking here. KJ_IF_MAYBE(segmentState, moreSegments) { KJ_DASSERT(segmentState->get()->forOutput.size() == segmentState->get()->builders.size() + 1, "segmentState->forOutput wasn't resized correctly when the last builder was added.", segmentState->get()->forOutput.size(), segmentState->get()->builders.size()); kj::ArrayPtr> result( &segmentState->get()->forOutput[0], segmentState->get()->forOutput.size()); uint i = 0; result[i++] = segment0.currentlyAllocated(); for (auto& builder: segmentState->get()->builders) { result[i++] = builder->currentlyAllocated(); } return result; } else { if (segment0.getArena() == nullptr) { // We haven't actually allocated any segments yet. return nullptr; } else { // We have only one segment so far. segment0ForOutput = segment0.currentlyAllocated(); return kj::arrayPtr(&segment0ForOutput, 1); } } } SegmentReader* BuilderArena::tryGetSegment(SegmentId id) { if (id == SegmentId(0)) { if (segment0.getArena() == nullptr) { // We haven't allocated any segments yet. return nullptr; } else { return &segment0; } } else { KJ_IF_MAYBE(segmentState, moreSegments) { if (id.value <= segmentState->get()->builders.size()) { // TODO(cleanup): Return a const SegmentReader and tediously constify all SegmentBuilder // pointers throughout the codebase. return const_cast(kj::implicitCast( segmentState->get()->builders[id.value - 1].get())); } } return nullptr; } } void BuilderArena::reportReadLimitReached() { KJ_FAIL_ASSERT("Read limit reached for BuilderArena, but it should have been unlimited.") { return; } } kj::Maybe> BuilderArena::LocalCapTable::extractCap(uint index) { #if CAPNP_LITE KJ_UNIMPLEMENTED("no cap tables in lite mode"); #else if (index < capTable.size()) { return capTable[index].map([](kj::Own& cap) { return cap->addRef(); }); } else { return nullptr; } #endif } uint BuilderArena::LocalCapTable::injectCap(kj::Own&& cap) { #if CAPNP_LITE KJ_UNIMPLEMENTED("no cap tables in lite mode"); #else uint result = capTable.size(); capTable.add(kj::mv(cap)); return result; #endif } void BuilderArena::LocalCapTable::dropCap(uint index) { #if CAPNP_LITE KJ_UNIMPLEMENTED("no cap tables in lite mode"); #else KJ_ASSERT(index < capTable.size(), "Invalid capability descriptor in message.") { return; } capTable[index] = nullptr; #endif } } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/capability-test.c++0000644000175000017500000012570514712011043022225 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "schema.capnp.h" #ifdef CAPNP_CAPABILITY_H_INCLUDED #error "schema.capnp should not depend on capability.h, because it contains no interfaces." #endif #include #ifndef CAPNP_CAPABILITY_H_INCLUDED #error "test.capnp did not include capability.h." #endif #include "capability.h" #include "test-util.h" #include #include namespace capnp { namespace _ { namespace { TEST(Capability, Basic) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestInterface::Client client(kj::heap(callCount)); auto request1 = client.fooRequest(); request1.setI(123); request1.setJ(true); auto promise1 = request1.send(); auto request2 = client.bazRequest(); initTestMessage(request2.initS()); auto promise2 = request2.send(); bool barFailed = false; auto request3 = client.barRequest(); auto promise3 = request3.send().then( [](Response&& response) { ADD_FAILURE() << "Expected bar() call to fail."; }, [&](kj::Exception&& e) { EXPECT_EQ(kj::Exception::Type::UNIMPLEMENTED, e.getType()); barFailed = true; }); EXPECT_EQ(0, callCount); auto response1 = promise1.wait(waitScope); EXPECT_EQ("foo", response1.getX()); auto response2 = promise2.wait(waitScope); promise3.wait(waitScope); EXPECT_EQ(2, callCount); EXPECT_TRUE(barFailed); } TEST(Capability, CapabilityList) { kj::EventLoop loop; kj::WaitScope waitScope(loop); MallocMessageBuilder builder; auto root = builder.initRoot(); auto initCapList = root.initCapList(2); int callCount0 = 0; int callCount1 = 0; initCapList.set(0, kj::heap(callCount0)); initCapList.set(1, kj::heap(callCount1)); auto capList = root.getCapList(); auto cap0 = capList[0].castAs(); auto cap1 = capList[1].castAs(); EXPECT_EQ(2u, root.getCapList().size()); auto request0 = cap0.fooRequest(); request0.setI(123); request0.setJ(true); EXPECT_EQ("foo", request0.send().wait(waitScope).getX()); auto request1 = cap1.fooRequest(); request1.setI(123); request1.setJ(true); EXPECT_EQ("foo", request1.send().wait(waitScope).getX()); EXPECT_EQ(1, callCount0); EXPECT_EQ(1, callCount1); } TEST(Capability, Inheritance) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestExtends::Client client1(kj::heap(callCount)); test::TestInterface::Client client2 = client1; auto client = client2.castAs(); auto request1 = client.fooRequest(); request1.setI(321); auto promise1 = request1.send(); auto request2 = client.graultRequest(); auto promise2 = request2.send(); EXPECT_EQ(0, callCount); auto response2 = promise2.wait(waitScope); checkTestMessage(response2); auto response1 = promise1.wait(waitScope); EXPECT_EQ("bar", response1.getX()); EXPECT_EQ(2, callCount); } TEST(Capability, Pipelining) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; test::TestPipeline::Client client(kj::heap(callCount)); auto request = client.getCapRequest(); request.setN(234); request.setInCap(test::TestInterface::Client(kj::heap(chainedCallCount))); auto promise = request.send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, chainedCallCount); } KJ_TEST("use pipeline after dropping response") { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; test::TestPipeline::Client client(kj::heap(callCount)); auto request = client.getCapRequest(); request.setN(234); request.setInCap(test::TestInterface::Client(kj::heap(chainedCallCount))); auto promise = request.send(); test::TestPipeline::GetCapResults::Pipeline pipeline = kj::mv(promise); { auto response = promise.wait(waitScope); KJ_EXPECT(response.getS() == "bar"); } auto pipelineRequest = pipeline.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = pipeline.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, chainedCallCount); } KJ_TEST("context.setPipeline") { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestPipeline::Client client(kj::heap(callCount)); auto promise = client.getCapPipelineOnlyRequest().send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); EXPECT_EQ(0, callCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); // The original promise never completed. KJ_EXPECT(!promise.poll(waitScope)); } TEST(Capability, TailCall) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int calleeCallCount = 0; int callerCallCount = 0; test::TestTailCallee::Client callee(kj::heap(calleeCallCount)); test::TestTailCaller::Client caller(kj::heap(callerCallCount)); auto request = caller.fooRequest(); request.setI(456); request.setCallee(callee); auto promise = request.send(); auto dependentCall0 = promise.getC().getCallSequenceRequest().send(); auto response = promise.wait(waitScope); EXPECT_EQ(456, response.getI()); EXPECT_EQ(456, response.getI()); auto dependentCall1 = promise.getC().getCallSequenceRequest().send(); auto dependentCall2 = response.getC().getCallSequenceRequest().send(); EXPECT_EQ(0, dependentCall0.wait(waitScope).getN()); EXPECT_EQ(1, dependentCall1.wait(waitScope).getN()); EXPECT_EQ(2, dependentCall2.wait(waitScope).getN()); EXPECT_EQ(1, calleeCallCount); EXPECT_EQ(1, callerCallCount); } TEST(Capability, AsyncCancelation) { // Tests cancellation. kj::EventLoop loop; kj::WaitScope waitScope(loop); auto paf = kj::newPromiseAndFulfiller(); bool destroyed = false; auto destructionPromise = paf.promise.then([&]() { destroyed = true; }).eagerlyEvaluate(nullptr); int callCount = 0; int handleCount = 0; test::TestMoreStuff::Client client(kj::heap(callCount, handleCount)); kj::Promise promise = nullptr; bool returned = false; { auto request = client.expectCancelRequest(); request.setCap(test::TestInterface::Client(kj::heap(kj::mv(paf.fulfiller)))); promise = request.send().then( [&](Response&& response) { returned = true; }).eagerlyEvaluate(nullptr); } kj::evalLater([]() {}).wait(waitScope); kj::evalLater([]() {}).wait(waitScope); // We can detect that the method was canceled because it will drop the cap. EXPECT_FALSE(destroyed); EXPECT_FALSE(returned); promise = nullptr; // request cancellation destructionPromise.wait(waitScope); EXPECT_TRUE(destroyed); EXPECT_FALSE(returned); } // ======================================================================================= TEST(Capability, DynamicClient) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; DynamicCapability::Client client = test::TestInterface::Client(kj::heap(callCount)); auto request1 = client.newRequest("foo"); request1.set("i", 123); request1.set("j", true); auto promise1 = request1.send(); auto request2 = client.newRequest("baz"); initDynamicTestMessage(request2.init("s").as()); auto promise2 = request2.send(); bool barFailed = false; auto request3 = client.newRequest("bar"); auto promise3 = request3.send().then( [](Response&& response) { ADD_FAILURE() << "Expected bar() call to fail."; }, [&](kj::Exception&& e) { EXPECT_EQ(kj::Exception::Type::UNIMPLEMENTED, e.getType()); barFailed = true; }); EXPECT_EQ(0, callCount); auto response1 = promise1.wait(waitScope); EXPECT_EQ("foo", response1.get("x").as()); auto response2 = promise2.wait(waitScope); promise3.wait(waitScope); EXPECT_EQ(2, callCount); EXPECT_TRUE(barFailed); } TEST(Capability, DynamicClientInheritance) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; DynamicCapability::Client client1 = test::TestExtends::Client(kj::heap(callCount)); EXPECT_EQ(Schema::from(), client1.getSchema()); EXPECT_NE(Schema::from(), client1.getSchema()); DynamicCapability::Client client2 = client1.upcast(Schema::from()); EXPECT_EQ(Schema::from(), client2.getSchema()); EXPECT_ANY_THROW(client2.upcast(Schema::from())); auto client = client2.castAs(Schema::from()); auto request1 = client.newRequest("foo"); request1.set("i", 321); auto promise1 = request1.send(); auto request2 = client.newRequest("grault"); auto promise2 = request2.send(); EXPECT_EQ(0, callCount); auto response2 = promise2.wait(waitScope); checkDynamicTestMessage(response2.as()); auto response1 = promise1.wait(waitScope); EXPECT_EQ("bar", response1.get("x").as()); EXPECT_EQ(2, callCount); } TEST(Capability, DynamicClientPipelining) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; DynamicCapability::Client client = test::TestPipeline::Client(kj::heap(callCount)); auto request = client.newRequest("getCap"); request.set("n", 234); request.set("inCap", test::TestInterface::Client(kj::heap(chainedCallCount))); auto promise = request.send(); auto outCap = promise.get("outBox").releaseAs() .get("cap").releaseAs(); auto pipelineRequest = outCap.newRequest("foo"); pipelineRequest.set("i", 321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = outCap.castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.get("x").as()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, chainedCallCount); } TEST(Capability, DynamicClientPipelineAnyCap) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; DynamicCapability::Client client = test::TestPipeline::Client(kj::heap(callCount)); auto request = client.newRequest("getAnyCap"); request.set("n", 234); request.set("inCap", test::TestInterface::Client(kj::heap(chainedCallCount))); auto promise = request.send(); auto outAnyCap = promise.get("outBox").releaseAs() .get("cap").releaseAs(); EXPECT_EQ(Schema::from(), outAnyCap.getSchema()); auto outCap = outAnyCap.castAs(Schema::from()); auto pipelineRequest = outCap.newRequest("foo"); pipelineRequest.set("i", 321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = outCap.castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.get("x").as()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, chainedCallCount); } // ======================================================================================= class TestInterfaceDynamicImpl final: public DynamicCapability::Server { public: TestInterfaceDynamicImpl(int& callCount) : DynamicCapability::Server(Schema::from()), callCount(callCount) {} int& callCount; kj::Promise call(InterfaceSchema::Method method, CallContext context) { auto methodName = method.getProto().getName(); if (methodName == "foo") { ++callCount; auto params = context.getParams(); EXPECT_EQ(123, params.get("i").as()); EXPECT_TRUE(params.get("j").as()); context.getResults().set("x", "foo"); return kj::READY_NOW; } else if (methodName == "baz") { ++callCount; auto params = context.getParams(); checkDynamicTestMessage(params.get("s").as()); context.releaseParams(); EXPECT_ANY_THROW(context.getParams()); return kj::READY_NOW; } else { KJ_UNIMPLEMENTED("Method not implemented", methodName) { break; } return kj::READY_NOW; } } }; TEST(Capability, DynamicServer) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestInterface::Client client = DynamicCapability::Client(kj::heap(callCount)) .castAs(); auto request1 = client.fooRequest(); request1.setI(123); request1.setJ(true); auto promise1 = request1.send(); auto request2 = client.bazRequest(); initTestMessage(request2.initS()); auto promise2 = request2.send(); bool barFailed = false; auto request3 = client.barRequest(); auto promise3 = request3.send().then( [](Response&& response) { ADD_FAILURE() << "Expected bar() call to fail."; }, [&](kj::Exception&& e) { EXPECT_EQ(kj::Exception::Type::UNIMPLEMENTED, e.getType()); barFailed = true; }); EXPECT_EQ(0, callCount); auto response1 = promise1.wait(waitScope); EXPECT_EQ("foo", response1.getX()); auto response2 = promise2.wait(waitScope); promise3.wait(waitScope); EXPECT_EQ(2, callCount); EXPECT_TRUE(barFailed); } class TestExtendsDynamicImpl final: public DynamicCapability::Server { public: TestExtendsDynamicImpl(int& callCount) : DynamicCapability::Server(Schema::from()), callCount(callCount) {} int& callCount; kj::Promise call(InterfaceSchema::Method method, CallContext context) { auto methodName = method.getProto().getName(); if (methodName == "foo") { ++callCount; auto params = context.getParams(); EXPECT_EQ(321, params.get("i").as()); EXPECT_FALSE(params.get("j").as()); context.getResults().set("x", "bar"); return kj::READY_NOW; } else if (methodName == "grault") { ++callCount; context.releaseParams(); initDynamicTestMessage(context.getResults()); return kj::READY_NOW; } else { KJ_FAIL_ASSERT("Method not implemented", methodName); } } }; TEST(Capability, DynamicServerInheritance) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestExtends::Client client1 = DynamicCapability::Client(kj::heap(callCount)) .castAs(); test::TestInterface::Client client2 = client1; auto client = client2.castAs(); auto request1 = client.fooRequest(); request1.setI(321); auto promise1 = request1.send(); auto request2 = client.graultRequest(); auto promise2 = request2.send(); EXPECT_EQ(0, callCount); auto response2 = promise2.wait(waitScope); checkTestMessage(response2); auto response1 = promise1.wait(waitScope); EXPECT_EQ("bar", response1.getX()); EXPECT_EQ(2, callCount); } class TestPipelineDynamicImpl final: public DynamicCapability::Server { public: TestPipelineDynamicImpl(int& callCount) : DynamicCapability::Server(Schema::from()), callCount(callCount) {} int& callCount; kj::Promise call(InterfaceSchema::Method method, CallContext context) { auto methodName = method.getProto().getName(); if (methodName == "getCap") { ++callCount; auto params = context.getParams(); EXPECT_EQ(234, params.get("n").as()); auto cap = params.get("inCap").as(); context.releaseParams(); auto request = cap.newRequest("foo"); request.set("i", 123); request.set("j", true); return request.send().then( [this,KJ_CPCAP(context)](capnp::Response&& response) mutable { EXPECT_EQ("foo", response.get("x").as()); auto result = context.getResults(); result.set("s", "bar"); auto box = result.init("outBox").as(); // Too lazy to write a whole separate test for each of these cases... so just make // sure they both compile here, and only actually test the latter. box.set("cap", kj::heap(callCount)); #if __GNUG__ && !__clang__ && __GNUG__ == 4 && __GNUC_MINOR__ == 9 // The last line in this block tickles a bug in Debian G++ 4.9.2 that is not present // in 4.8.x nor in 4.9.4: // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=781060 // // Unfortunately 4.9.2 is present on many Debian Jessie systems.. // // For the moment, we can get away with skipping the last line as the previous line // will set things up in a way that allows the test to complete successfully. return; #endif box.set("cap", kj::heap(callCount)); }); } else { KJ_FAIL_ASSERT("Method not implemented", methodName); } } }; TEST(Capability, DynamicServerPipelining) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; test::TestPipeline::Client client = DynamicCapability::Client(kj::heap(callCount)) .castAs(); auto request = client.getCapRequest(); request.setN(234); request.setInCap(test::TestInterface::Client(kj::heap(chainedCallCount))); auto promise = request.send(); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); auto pipelineRequest2 = promise.getOutBox().getCap().castAs().graultRequest(); auto pipelinePromise2 = pipelineRequest2.send(); promise = nullptr; // Just to be annoying, drop the original promise. EXPECT_EQ(0, callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.getX()); auto response2 = pipelinePromise2.wait(waitScope); checkTestMessage(response2); EXPECT_EQ(3, callCount); EXPECT_EQ(1, chainedCallCount); } class TestTailCallerDynamicImpl final: public DynamicCapability::Server { public: TestTailCallerDynamicImpl(int& callCount) : DynamicCapability::Server(Schema::from()), callCount(callCount) {} int& callCount; kj::Promise call(InterfaceSchema::Method method, CallContext context) { auto methodName = method.getProto().getName(); if (methodName == "foo") { ++callCount; auto params = context.getParams(); auto tailRequest = params.get("callee").as().newRequest("foo"); tailRequest.set("i", params.get("i")); tailRequest.set("t", "from TestTailCaller"); return context.tailCall(kj::mv(tailRequest)); } else { KJ_FAIL_ASSERT("Method not implemented", methodName); } } }; TEST(Capability, DynamicServerTailCall) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int calleeCallCount = 0; int callerCallCount = 0; test::TestTailCallee::Client callee(kj::heap(calleeCallCount)); test::TestTailCaller::Client caller = DynamicCapability::Client(kj::heap(callerCallCount)) .castAs(); auto request = caller.fooRequest(); request.setI(456); request.setCallee(callee); auto promise = request.send(); auto dependentCall0 = promise.getC().getCallSequenceRequest().send(); auto response = promise.wait(waitScope); EXPECT_EQ(456, response.getI()); EXPECT_EQ(456, response.getI()); auto dependentCall1 = promise.getC().getCallSequenceRequest().send(); auto dependentCall2 = response.getC().getCallSequenceRequest().send(); EXPECT_EQ(0, dependentCall0.wait(waitScope).getN()); EXPECT_EQ(1, dependentCall1.wait(waitScope).getN()); EXPECT_EQ(2, dependentCall2.wait(waitScope).getN()); EXPECT_EQ(1, calleeCallCount); EXPECT_EQ(1, callerCallCount); } // ======================================================================================= void verifyClient(test::TestInterface::Client client, const int& callCount, kj::WaitScope& waitScope) { int origCount = callCount; auto request = client.fooRequest(); request.setI(123); request.setJ(true); auto response = request.send().wait(waitScope); EXPECT_EQ("foo", response.getX()); EXPECT_EQ(origCount + 1, callCount); } void verifyClient(DynamicCapability::Client client, const int& callCount, kj::WaitScope& waitScope) { int origCount = callCount; auto request = client.newRequest("foo"); request.set("i", 123); request.set("j", true); auto response = request.send().wait(waitScope); EXPECT_EQ("foo", response.get("x").as()); EXPECT_EQ(origCount + 1, callCount); } TEST(Capability, AnyPointersAndOrphans) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount1 = 0; int callCount2 = 0; // We use a TestPipeline instance here merely as a way to conveniently obtain an imbued message // instance. test::TestPipeline::Client baseClient(nullptr); test::TestInterface::Client client1(kj::heap(callCount1)); test::TestInterface::Client client2(kj::heap(callCount2)); auto request = baseClient.testPointersRequest(); request.setCap(client1); EXPECT_TRUE(request.hasCap()); Orphan orphan = request.disownCap(); EXPECT_FALSE(orphan == nullptr); EXPECT_FALSE(request.hasCap()); verifyClient(orphan.get(), callCount1, waitScope); verifyClient(orphan.getReader(), callCount1, waitScope); request.getObj().adopt(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); verifyClient(request.getObj().getAs(), callCount1, waitScope); verifyClient(request.asReader().getObj().getAs(), callCount1, waitScope); verifyClient(request.getObj().getAs( Schema::from()), callCount1, waitScope); verifyClient(request.asReader().getObj().getAs( Schema::from()), callCount1, waitScope); request.getObj().clear(); EXPECT_FALSE(request.hasObj()); request.getObj().setAs(client2); verifyClient(request.getObj().getAs(), callCount2, waitScope); Orphan dynamicOrphan = request.getObj().disownAs( Schema::from()); verifyClient(dynamicOrphan.get(), callCount2, waitScope); verifyClient(dynamicOrphan.getReader(), callCount2, waitScope); Orphan dynamicValueOrphan = kj::mv(dynamicOrphan); verifyClient(dynamicValueOrphan.get().as(), callCount2, waitScope); orphan = dynamicValueOrphan.releaseAs(); EXPECT_FALSE(orphan == nullptr); verifyClient(orphan.get(), callCount2, waitScope); request.adoptCap(kj::mv(orphan)); EXPECT_TRUE(orphan == nullptr); verifyClient(request.getCap(), callCount2, waitScope); Orphan dynamicOrphan2 = request.disownCap(); verifyClient(dynamicOrphan2.get(), callCount2, waitScope); verifyClient(dynamicOrphan2.getReader(), callCount2, waitScope); } TEST(Capability, Lists) { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount1 = 0; int callCount2 = 0; int callCount3 = 0; test::TestPipeline::Client baseClient(kj::heap(callCount1)); test::TestInterface::Client client1(kj::heap(callCount1)); test::TestInterface::Client client2(kj::heap(callCount2)); test::TestInterface::Client client3(kj::heap(callCount3)); auto request = baseClient.testPointersRequest(); auto list = request.initList(3); list.set(0, client1); list.set(1, client2); list.set(2, client3); verifyClient(list[0], callCount1, waitScope); verifyClient(list[1], callCount2, waitScope); verifyClient(list[2], callCount3, waitScope); auto listReader = request.asReader().getList(); verifyClient(listReader[0], callCount1, waitScope); verifyClient(listReader[1], callCount2, waitScope); verifyClient(listReader[2], callCount3, waitScope); auto dynamicList = toDynamic(list); verifyClient(dynamicList[0].as(), callCount1, waitScope); verifyClient(dynamicList[1].as(), callCount2, waitScope); verifyClient(dynamicList[2].as(), callCount3, waitScope); auto dynamicListReader = toDynamic(listReader); verifyClient(dynamicListReader[0].as(), callCount1, waitScope); verifyClient(dynamicListReader[1].as(), callCount2, waitScope); verifyClient(dynamicListReader[2].as(), callCount3, waitScope); } TEST(Capability, KeywordMethods) { // Verify that keywords are only munged where necessary. kj::EventLoop loop; kj::WaitScope waitScope(loop); bool called = false; class TestKeywordMethodsImpl final: public test::TestKeywordMethods::Server { public: TestKeywordMethodsImpl(bool& called): called(called) {} kj::Promise delete_(DeleteContext context) override { called = true; return kj::READY_NOW; } private: bool& called; }; test::TestKeywordMethods::Client client = kj::heap(called); client.deleteRequest().send().wait(waitScope); EXPECT_TRUE(called); } TEST(Capability, Generics) { kj::EventLoop loop; kj::WaitScope waitScope(loop); typedef test::TestGenerics::Interface> Interface; Interface::Client client = nullptr; auto request = client.callRequest(); request.setBaz("hello"); initTestMessage(request.initInnerBound().initFoo()); initTestMessage(request.initInnerUnbound().getFoo().initAs()); auto promise = request.send().then([](capnp::Response&& response) { // This doesn't actually execute; we're just checking that it compiles. List::Reader qux = response.getQux(); qux.size(); checkTestMessage(response.getGen().getFoo()); }, [](kj::Exception&& e) { // Ignore exception (which we'll always get because we're calling a null capability). }); promise.wait(waitScope); // Check that asGeneric<>() compiles. test::TestGenerics::Interface<>::Client castClient = client.asGeneric<>(); test::TestGenerics::Interface::Client castClient2 = client.asGeneric(); test::TestGenerics<>::Interface>::Client castClient3 = client.asTestGenericsGeneric<>(); } TEST(Capability, Generics2) { MallocMessageBuilder builder; auto root = builder.getRoot(); root.initCap().setFoo(test::TestInterface::Client(nullptr)); } TEST(Capability, ImplicitParams) { kj::EventLoop loop; kj::WaitScope waitScope(loop); typedef test::TestImplicitMethodParams Interface; Interface::Client client = nullptr; capnp::Request, test::TestGenerics> request = client.callRequest(); request.setFoo("hello"); initTestMessage(request.initBar()); auto promise = request.send() .then([](capnp::Response>&& response) { // This doesn't actually execute; we're just checking that it compiles. Text::Reader text = response.getFoo(); text.size(); checkTestMessage(response.getRev().getFoo()); }, [](kj::Exception&& e) {}); promise.wait(waitScope); } TEST(Capability, CapabilityServerSet) { kj::EventLoop loop; kj::WaitScope waitScope(loop); CapabilityServerSet set1, set2; int callCount = 0; test::TestInterface::Client clientStandalone(kj::heap(callCount)); test::TestInterface::Client clientNull = nullptr; auto ownServer1 = kj::heap(callCount); auto& server1 = *ownServer1; test::TestInterface::Client client1 = set1.add(kj::mv(ownServer1)); auto ownServer2 = kj::heap(callCount); auto& server2 = *ownServer2; test::TestInterface::Client client2 = set2.add(kj::mv(ownServer2)); // Getting the local server using the correct set works. EXPECT_EQ(&server1, &KJ_ASSERT_NONNULL(set1.getLocalServer(client1).wait(waitScope))); EXPECT_EQ(&server2, &KJ_ASSERT_NONNULL(set2.getLocalServer(client2).wait(waitScope))); // Getting the local server using the wrong set doesn't work. EXPECT_TRUE(set1.getLocalServer(client2).wait(waitScope) == nullptr); EXPECT_TRUE(set2.getLocalServer(client1).wait(waitScope) == nullptr); EXPECT_TRUE(set1.getLocalServer(clientStandalone).wait(waitScope) == nullptr); EXPECT_TRUE(set1.getLocalServer(clientNull).wait(waitScope) == nullptr); // A promise client waits to be resolved. auto paf = kj::newPromiseAndFulfiller(); test::TestInterface::Client clientPromise = kj::mv(paf.promise); auto errorPaf = kj::newPromiseAndFulfiller(); test::TestInterface::Client errorPromise = kj::mv(errorPaf.promise); bool resolved1 = false, resolved2 = false, resolved3 = false; auto promise1 = set1.getLocalServer(clientPromise) .then([&](kj::Maybe server) { resolved1 = true; EXPECT_EQ(&server1, &KJ_ASSERT_NONNULL(server)); }); auto promise2 = set2.getLocalServer(clientPromise) .then([&](kj::Maybe server) { resolved2 = true; EXPECT_TRUE(server == nullptr); }); auto promise3 = set1.getLocalServer(errorPromise) .then([&](kj::Maybe server) { KJ_FAIL_EXPECT("getLocalServer() on error promise should have thrown"); }, [&](kj::Exception&& e) { resolved3 = true; KJ_EXPECT(e.getDescription().endsWith("foo"), e.getDescription()); }); kj::evalLater([](){}).wait(waitScope); kj::evalLater([](){}).wait(waitScope); kj::evalLater([](){}).wait(waitScope); kj::evalLater([](){}).wait(waitScope); EXPECT_FALSE(resolved1); EXPECT_FALSE(resolved2); EXPECT_FALSE(resolved3); paf.fulfiller->fulfill(kj::cp(client1)); errorPaf.fulfiller->reject(KJ_EXCEPTION(FAILED, "foo")); promise1.wait(waitScope); promise2.wait(waitScope); promise3.wait(waitScope); EXPECT_TRUE(resolved1); EXPECT_TRUE(resolved2); EXPECT_TRUE(resolved3); } class TestThisCap final: public test::TestInterface::Server { public: TestThisCap(int& callCount): callCount(callCount) {} ~TestThisCap() noexcept(false) { callCount = -1; } test::TestInterface::Client getSelf() { return thisCap(); } protected: kj::Promise bar(BarContext context) { ++callCount; return kj::READY_NOW; } private: int& callCount; }; TEST(Capability, ThisCap) { int callCount = 0; kj::EventLoop loop; kj::WaitScope waitScope(loop); auto server = kj::heap(callCount); TestThisCap* serverPtr = server; test::TestInterface::Client client = kj::mv(server); client.barRequest().send().wait(waitScope); EXPECT_EQ(1, callCount); test::TestInterface::Client client2 = serverPtr->getSelf(); EXPECT_EQ(1, callCount); client2.barRequest().send().wait(waitScope); EXPECT_EQ(2, callCount); client = nullptr; EXPECT_EQ(2, callCount); client2.barRequest().send().wait(waitScope); EXPECT_EQ(3, callCount); client2 = nullptr; EXPECT_EQ(-1, callCount); } TEST(Capability, TransferCap) { kj::EventLoop loop; kj::WaitScope waitScope(loop); MallocMessageBuilder message; auto root = message.initRoot(); auto orphan = message.getOrphanage().newOrphan(); auto e = orphan.get(); e.setText("foo"); e.setCap(KJ_EXCEPTION(FAILED, "whatever")); root.initList(1).adoptWithCaveats(0, kj::mv(orphan)); // This line used to throw due to capability pointers being incorrectly transferred. auto cap = root.getList()[0].getCap(); cap.whenResolved().then([]() { KJ_FAIL_EXPECT("didn't throw?"); }, [](kj::Exception&&) { // success }).wait(waitScope); } KJ_TEST("Promise> automatically reduces to RemotePromise") { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; test::TestInterface::Client client(kj::heap(callCount)); RemotePromise promise = kj::evalLater([&]() { auto request = client.fooRequest(); request.setI(123); request.setJ(true); return request.send(); }); EXPECT_EQ(0, callCount); auto response = promise.wait(waitScope); EXPECT_EQ("foo", response.getX()); EXPECT_EQ(1, callCount); } KJ_TEST("Promise> automatically reduces to RemotePromise with pipelining") { kj::EventLoop loop; kj::WaitScope waitScope(loop); int callCount = 0; int chainedCallCount = 0; test::TestPipeline::Client client(kj::heap(callCount)); auto promise = kj::evalLater([&]() { auto request = client.getCapRequest(); request.setN(234); request.setInCap(test::TestInterface::Client(kj::heap(chainedCallCount))); return request.send(); }); auto pipelineRequest = promise.getOutBox().getCap().fooRequest(); pipelineRequest.setI(321); auto pipelinePromise = pipelineRequest.send(); EXPECT_EQ(0, callCount); EXPECT_EQ(0, chainedCallCount); auto response = pipelinePromise.wait(waitScope); EXPECT_EQ("bar", response.getX()); EXPECT_EQ(2, callCount); EXPECT_EQ(1, chainedCallCount); } KJ_TEST("clone() with caps") { int dummy = 0; MallocMessageBuilder builder(2048); auto root = builder.getRoot().initAs>(3); root.set(0, kj::heap(dummy)); root.set(1, kj::heap(dummy)); root.set(2, kj::heap(dummy)); auto copyPtr = clone(root.asReader()); auto& copy = *copyPtr; KJ_ASSERT(copy.size() == 3); KJ_EXPECT(ClientHook::from(copy[0]).get() == ClientHook::from(root[0]).get()); KJ_EXPECT(ClientHook::from(copy[1]).get() == ClientHook::from(root[1]).get()); KJ_EXPECT(ClientHook::from(copy[2]).get() == ClientHook::from(root[2]).get()); KJ_EXPECT(ClientHook::from(copy[0]).get() != ClientHook::from(root[1]).get()); KJ_EXPECT(ClientHook::from(copy[1]).get() != ClientHook::from(root[2]).get()); KJ_EXPECT(ClientHook::from(copy[2]).get() != ClientHook::from(root[0]).get()); } KJ_TEST("Streaming calls block subsequent calls") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto ownServer = kj::heap(); auto& server = *ownServer; test::TestStreaming::Client cap = kj::mv(ownServer); kj::Promise promise1 = nullptr, promise2 = nullptr, promise3 = nullptr; { auto req = cap.doStreamIRequest(); req.setI(123); promise1 = req.send(); } { auto req = cap.doStreamJRequest(); req.setJ(321); promise2 = req.send(); } { auto req = cap.doStreamIRequest(); req.setI(456); promise3 = req.send(); } auto promise4 = cap.finishStreamRequest().send(); KJ_EXPECT(server.iSum == 0); KJ_EXPECT(server.jSum == 0); KJ_EXPECT(!promise1.poll(waitScope)); KJ_EXPECT(!promise2.poll(waitScope)); KJ_EXPECT(!promise3.poll(waitScope)); KJ_EXPECT(!promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 123); KJ_EXPECT(server.jSum == 0); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(promise1.poll(waitScope)); KJ_EXPECT(!promise2.poll(waitScope)); KJ_EXPECT(!promise3.poll(waitScope)); KJ_EXPECT(!promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 123); KJ_EXPECT(server.jSum == 321); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(promise1.poll(waitScope)); KJ_EXPECT(promise2.poll(waitScope)); KJ_EXPECT(!promise3.poll(waitScope)); KJ_EXPECT(!promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 579); KJ_EXPECT(server.jSum == 321); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(promise1.poll(waitScope)); KJ_EXPECT(promise2.poll(waitScope)); KJ_EXPECT(promise3.poll(waitScope)); KJ_EXPECT(promise4.poll(waitScope)); auto result = promise4.wait(waitScope); KJ_EXPECT(result.getTotalI() == 579); KJ_EXPECT(result.getTotalJ() == 321); } KJ_TEST("Streaming calls can be canceled") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto ownServer = kj::heap(); auto& server = *ownServer; test::TestStreaming::Client cap = kj::mv(ownServer); kj::Promise promise1 = nullptr, promise2 = nullptr, promise3 = nullptr; { auto req = cap.doStreamIRequest(); req.setI(123); promise1 = req.send(); } { auto req = cap.doStreamJRequest(); req.setJ(321); promise2 = req.send(); } { auto req = cap.doStreamIRequest(); req.setI(456); promise3 = req.send(); } auto promise4 = cap.finishStreamRequest().send(); // Cancel the doStreamJ() request. promise2 = nullptr; KJ_EXPECT(server.iSum == 0); KJ_EXPECT(server.jSum == 0); KJ_EXPECT(!promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 123); KJ_EXPECT(server.jSum == 0); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(!promise4.poll(waitScope)); // The call to doStreamJ() was canceled, so the next call to doStreamI() happens immediately. KJ_EXPECT(server.iSum == 579); KJ_EXPECT(server.jSum == 0); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(promise4.poll(waitScope)); auto result = promise4.wait(waitScope); KJ_EXPECT(result.getTotalI() == 579); KJ_EXPECT(result.getTotalJ() == 0); } KJ_TEST("Streaming call throwing cascades to following calls") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto ownServer = kj::heap(); auto& server = *ownServer; test::TestStreaming::Client cap = kj::mv(ownServer); server.jShouldThrow = true; kj::Promise promise1 = nullptr, promise2 = nullptr, promise3 = nullptr; { auto req = cap.doStreamIRequest(); req.setI(123); promise1 = req.send(); } { auto req = cap.doStreamJRequest(); req.setJ(321); promise2 = req.send(); } { auto req = cap.doStreamIRequest(); req.setI(456); promise3 = req.send(); } auto promise4 = cap.finishStreamRequest().send(); KJ_EXPECT(server.iSum == 0); KJ_EXPECT(server.jSum == 0); KJ_EXPECT(!promise1.poll(waitScope)); KJ_EXPECT(!promise2.poll(waitScope)); KJ_EXPECT(!promise3.poll(waitScope)); KJ_EXPECT(!promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 123); KJ_EXPECT(server.jSum == 0); KJ_ASSERT_NONNULL(server.fulfiller)->fulfill(); KJ_EXPECT(promise1.poll(waitScope)); KJ_EXPECT(promise2.poll(waitScope)); KJ_EXPECT(promise3.poll(waitScope)); KJ_EXPECT(promise4.poll(waitScope)); KJ_EXPECT(server.iSum == 123); KJ_EXPECT(server.jSum == 321); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("throw requested", promise2.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("throw requested", promise3.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("throw requested", promise4.ignoreResult().wait(waitScope)); } KJ_TEST("RevocableServer") { kj::EventLoop loop; kj::WaitScope waitScope(loop); class ServerImpl: public test::TestMembrane::Server { public: kj::Promise waitForever(WaitForeverContext context) override { return kj::NEVER_DONE; } }; ServerImpl server; RevocableServer revocable(server); auto promise = revocable.getClient().waitForeverRequest().send(); KJ_EXPECT(!promise.poll(waitScope)); revocable.revoke(); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE( "capability was revoked", promise.ignoreResult().wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE( "capability was revoked", revocable.getClient().waitForeverRequest().send().ignoreResult().wait(waitScope)); } } // namespace } // namespace _ } // namespace capnp capnproto-c++-1.1.0/src/capnp/c++.capnp.h0000644000175000017500000000167314731562162020471 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: c++.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(b9c6f99ebf805f2c); CAPNP_DECLARE_SCHEMA(f264a779fef191ce); CAPNP_DECLARE_SCHEMA(ac7096ff8cfc9dce); } // namespace schemas } // namespace capnp namespace capnp { namespace annotations { // ======================================================================================= // ======================================================================================= } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/ez-rpc.c++0000644000175000017500000003156214712011043020324 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "ez-rpc.h" #include "rpc-twoparty.h" #include #include #include #include #include namespace capnp { KJ_THREADLOCAL_PTR(EzRpcContext) threadEzContext = nullptr; class EzRpcContext: public kj::Refcounted { public: EzRpcContext(): ioContext(kj::setupAsyncIo()) { threadEzContext = this; } ~EzRpcContext() noexcept(false) { KJ_REQUIRE(threadEzContext == this, "EzRpcContext destroyed from different thread than it was created.") { return; } threadEzContext = nullptr; } kj::WaitScope& getWaitScope() { return ioContext.waitScope; } kj::AsyncIoProvider& getIoProvider() { return *ioContext.provider; } kj::LowLevelAsyncIoProvider& getLowLevelIoProvider() { return *ioContext.lowLevelProvider; } static kj::Own getThreadLocal() { EzRpcContext* existing = threadEzContext; if (existing != nullptr) { return kj::addRef(*existing); } else { return kj::refcounted(); } } private: kj::AsyncIoContext ioContext; }; // ======================================================================================= kj::Promise> connectAttach(kj::Own&& addr) { return addr->connect().attach(kj::mv(addr)); } struct EzRpcClient::Impl { kj::Own context; struct ClientContext { kj::Own stream; TwoPartyVatNetwork network; RpcSystem rpcSystem; ClientContext(kj::Own&& stream, ReaderOptions readerOpts) : stream(kj::mv(stream)), network(*this->stream, rpc::twoparty::Side::CLIENT, readerOpts), rpcSystem(makeRpcClient(network)) {} Capability::Client getMain() { word scratch[4]; memset(scratch, 0, sizeof(scratch)); MallocMessageBuilder message(scratch); auto hostId = message.getRoot(); hostId.setSide(rpc::twoparty::Side::SERVER); return rpcSystem.bootstrap(hostId); } Capability::Client restore(kj::StringPtr name) { word scratch[64]; memset(scratch, 0, sizeof(scratch)); MallocMessageBuilder message(scratch); auto hostIdOrphan = message.getOrphanage().newOrphan(); auto hostId = hostIdOrphan.get(); hostId.setSide(rpc::twoparty::Side::SERVER); auto objectId = message.getRoot(); objectId.setAs(name); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" return rpcSystem.restore(hostId, objectId); #pragma GCC diagnostic pop } }; kj::ForkedPromise setupPromise; kj::Maybe> clientContext; // Filled in before `setupPromise` resolves. Impl(kj::StringPtr serverAddress, uint defaultPort, ReaderOptions readerOpts) : context(EzRpcContext::getThreadLocal()), setupPromise(context->getIoProvider().getNetwork() .parseAddress(serverAddress, defaultPort) .then([](kj::Own&& addr) { return connectAttach(kj::mv(addr)); }).then([this, readerOpts](kj::Own&& stream) { clientContext = kj::heap(kj::mv(stream), readerOpts); }).fork()) {} Impl(const struct sockaddr* serverAddress, uint addrSize, ReaderOptions readerOpts) : context(EzRpcContext::getThreadLocal()), setupPromise( connectAttach(context->getIoProvider().getNetwork() .getSockaddr(serverAddress, addrSize)) .then([this, readerOpts](kj::Own&& stream) { clientContext = kj::heap(kj::mv(stream), readerOpts); }).fork()) {} Impl(int socketFd, ReaderOptions readerOpts) : context(EzRpcContext::getThreadLocal()), setupPromise(kj::Promise(kj::READY_NOW).fork()), clientContext(kj::heap( context->getLowLevelIoProvider().wrapSocketFd(socketFd), readerOpts)) {} }; EzRpcClient::EzRpcClient(kj::StringPtr serverAddress, uint defaultPort, ReaderOptions readerOpts) : impl(kj::heap(serverAddress, defaultPort, readerOpts)) {} EzRpcClient::EzRpcClient(const struct sockaddr* serverAddress, uint addrSize, ReaderOptions readerOpts) : impl(kj::heap(serverAddress, addrSize, readerOpts)) {} EzRpcClient::EzRpcClient(int socketFd, ReaderOptions readerOpts) : impl(kj::heap(socketFd, readerOpts)) {} EzRpcClient::~EzRpcClient() noexcept(false) {} Capability::Client EzRpcClient::getMain() { KJ_IF_MAYBE(client, impl->clientContext) { return client->get()->getMain(); } else { return impl->setupPromise.addBranch().then([this]() { return KJ_ASSERT_NONNULL(impl->clientContext)->getMain(); }); } } Capability::Client EzRpcClient::importCap(kj::StringPtr name) { KJ_IF_MAYBE(client, impl->clientContext) { return client->get()->restore(name); } else { return impl->setupPromise.addBranch().then( [this,name=kj::heapString(name)]() { return KJ_ASSERT_NONNULL(impl->clientContext)->restore(name); }); } } kj::WaitScope& EzRpcClient::getWaitScope() { return impl->context->getWaitScope(); } kj::AsyncIoProvider& EzRpcClient::getIoProvider() { return impl->context->getIoProvider(); } kj::LowLevelAsyncIoProvider& EzRpcClient::getLowLevelIoProvider() { return impl->context->getLowLevelIoProvider(); } // ======================================================================================= namespace { class DummyFilter: public kj::LowLevelAsyncIoProvider::NetworkFilter { public: bool shouldAllow(const struct sockaddr* addr, uint addrlen) override { return true; } }; static DummyFilter DUMMY_FILTER; } // namespace struct EzRpcServer::Impl final: public SturdyRefRestorer, public kj::TaskSet::ErrorHandler { Capability::Client mainInterface; kj::Own context; struct ExportedCap { kj::String name; Capability::Client cap = nullptr; ExportedCap(kj::StringPtr name, Capability::Client cap) : name(kj::heapString(name)), cap(cap) {} ExportedCap() = default; ExportedCap(const ExportedCap&) = delete; ExportedCap(ExportedCap&&) = default; ExportedCap& operator=(const ExportedCap&) = delete; ExportedCap& operator=(ExportedCap&&) = default; // Make std::map happy... }; std::map exportMap; kj::ForkedPromise portPromise; kj::TaskSet tasks; struct ServerContext { kj::Own stream; TwoPartyVatNetwork network; RpcSystem rpcSystem; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" ServerContext(kj::Own&& stream, SturdyRefRestorer& restorer, ReaderOptions readerOpts) : stream(kj::mv(stream)), network(*this->stream, rpc::twoparty::Side::SERVER, readerOpts), rpcSystem(makeRpcServer(network, restorer)) {} #pragma GCC diagnostic pop }; Impl(Capability::Client mainInterface, kj::StringPtr bindAddress, uint defaultPort, ReaderOptions readerOpts) : mainInterface(kj::mv(mainInterface)), context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) { auto paf = kj::newPromiseAndFulfiller(); portPromise = paf.promise.fork(); tasks.add(context->getIoProvider().getNetwork().parseAddress(bindAddress, defaultPort) .then([this, portFulfiller=kj::mv(paf.fulfiller), readerOpts](kj::Own&& addr) mutable { auto listener = addr->listen(); portFulfiller->fulfill(listener->getPort()); acceptLoop(kj::mv(listener), readerOpts); })); } Impl(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts) : mainInterface(kj::mv(mainInterface)), context(EzRpcContext::getThreadLocal()), portPromise(nullptr), tasks(*this) { auto listener = context->getIoProvider().getNetwork() .getSockaddr(bindAddress, addrSize)->listen(); portPromise = kj::Promise(listener->getPort()).fork(); acceptLoop(kj::mv(listener), readerOpts); } Impl(Capability::Client mainInterface, int socketFd, uint port, ReaderOptions readerOpts) : mainInterface(kj::mv(mainInterface)), context(EzRpcContext::getThreadLocal()), portPromise(kj::Promise(port).fork()), tasks(*this) { acceptLoop(context->getLowLevelIoProvider().wrapListenSocketFd(socketFd, DUMMY_FILTER), readerOpts); } void acceptLoop(kj::Own&& listener, ReaderOptions readerOpts) { auto ptr = listener.get(); tasks.add(ptr->accept().then([this, listener=kj::mv(listener), readerOpts](kj::Own&& connection) mutable { acceptLoop(kj::mv(listener), readerOpts); auto server = kj::heap(kj::mv(connection), *this, readerOpts); // Arrange to destroy the server context when all references are gone, or when the // EzRpcServer is destroyed (which will destroy the TaskSet). tasks.add(server->network.onDisconnect().attach(kj::mv(server))); })); } Capability::Client restore(AnyPointer::Reader objectId) override { if (objectId.isNull()) { return mainInterface; } else { auto name = objectId.getAs(); auto iter = exportMap.find(name); if (iter == exportMap.end()) { KJ_FAIL_REQUIRE("Server exports no such capability.", name) { break; } return nullptr; } else { return iter->second.cap; } } } void taskFailed(kj::Exception&& exception) override { kj::throwFatalException(kj::mv(exception)); } }; EzRpcServer::EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress, uint defaultPort, ReaderOptions readerOpts) : impl(kj::heap(kj::mv(mainInterface), bindAddress, defaultPort, readerOpts)) {} EzRpcServer::EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts) : impl(kj::heap(kj::mv(mainInterface), bindAddress, addrSize, readerOpts)) {} EzRpcServer::EzRpcServer(Capability::Client mainInterface, int socketFd, uint port, ReaderOptions readerOpts) : impl(kj::heap(kj::mv(mainInterface), socketFd, port, readerOpts)) {} EzRpcServer::EzRpcServer(kj::StringPtr bindAddress, uint defaultPort, ReaderOptions readerOpts) : EzRpcServer(nullptr, bindAddress, defaultPort, readerOpts) {} EzRpcServer::EzRpcServer(struct sockaddr* bindAddress, uint addrSize, ReaderOptions readerOpts) : EzRpcServer(nullptr, bindAddress, addrSize, readerOpts) {} EzRpcServer::EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts) : EzRpcServer(nullptr, socketFd, port, readerOpts) {} EzRpcServer::~EzRpcServer() noexcept(false) {} void EzRpcServer::exportCap(kj::StringPtr name, Capability::Client cap) { Impl::ExportedCap entry(kj::heapString(name), cap); impl->exportMap[entry.name] = kj::mv(entry); } kj::Promise EzRpcServer::getPort() { return impl->portPromise.addBranch(); } kj::WaitScope& EzRpcServer::getWaitScope() { return impl->context->getWaitScope(); } kj::AsyncIoProvider& EzRpcServer::getIoProvider() { return impl->context->getIoProvider(); } kj::LowLevelAsyncIoProvider& EzRpcServer::getLowLevelIoProvider() { return impl->context->getLowLevelIoProvider(); } } // namespace capnp capnproto-c++-1.1.0/src/capnp/test-import2.capnp0000644000175000017500000000262414527152321022234 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xc64a3bf0338a124a; using Import1 = import "/capnp/schema.capnp"; using Import2 = import "test-import.capnp"; using Import3 = import "test.capnp"; struct TestImport2 { foo @0 :Import3.TestAllTypes; bar @1 :Import1.Node; baz @2 :Import2.TestImport; } capnproto-c++-1.1.0/src/capnp/stringify-test.c++0000644000175000017500000005773414527152321022141 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "message.h" #include "dynamic.h" #include "pretty-print.h" #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { TEST(Stringify, KjStringification) { MallocMessageBuilder builder; auto root = builder.initRoot(); // This test got ugly after printing was changed to always print primitives even when they have // default values... EXPECT_EQ("(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "enumField = foo, " "interfaceField = void)", kj::str(root)); initTestMessage(root); EXPECT_EQ("(" "voidField = void, " "boolField = true, " "int8Field = -123, " "int16Field = -12345, " "int32Field = -12345678, " "int64Field = -123456789012345, " "uInt8Field = 234, " "uInt16Field = 45678, " "uInt32Field = 3456789012, " "uInt64Field = 12345678901234567890, " "float32Field = 1234.5, " "float64Field = -1.23e47, " "textField = \"foo\", " "dataField = \"bar\", " "structField = (" "voidField = void, " "boolField = true, " "int8Field = -12, " "int16Field = 3456, " "int32Field = -78901234, " "int64Field = 56789012345678, " "uInt8Field = 90, " "uInt16Field = 1234, " "uInt32Field = 56789012, " "uInt64Field = 345678901234567890, " "float32Field = -1.25e-10, " "float64Field = 345, " "textField = \"baz\", " "dataField = \"qux\", " "structField = (" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"nested\", " "structField = (" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"really nested\", " "enumField = foo, " "interfaceField = void), " "enumField = foo, " "interfaceField = void), " "enumField = baz, " "interfaceField = void, " "voidList = [void, void, void], " "boolList = [false, true, false, true, true], " "int8List = [12, -34, -128, 127], " "int16List = [1234, -5678, -32768, 32767], " "int32List = [12345678, -90123456, -2147483648, 2147483647], " "int64List = [123456789012345, -678901234567890, " "-9223372036854775808, 9223372036854775807], " "uInt8List = [12, 34, 0, 255], " "uInt16List = [1234, 5678, 0, 65535], " "uInt32List = [12345678, 90123456, 0, 4294967295], " "uInt64List = [123456789012345, 678901234567890, 0, 18446744073709551615], " "float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], " "float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], " "textList = [\"quux\", \"corge\", \"grault\"], " "dataList = [\"garply\", \"waldo\", \"fred\"], " "structList = [" "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"x structlist 1\", " "enumField = foo, " "interfaceField = void), " "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"x structlist 2\", " "enumField = foo, " "interfaceField = void), " "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"x structlist 3\", " "enumField = foo, " "interfaceField = void)], " "enumList = [qux, bar, grault]), " "enumField = corge, " "interfaceField = void, " "voidList = [void, void, void, void, void, void], " "boolList = [true, false, false, true], " "int8List = [111, -111], " "int16List = [11111, -11111], " "int32List = [111111111, -111111111], " "int64List = [1111111111111111111, -1111111111111111111], " "uInt8List = [111, 222], " "uInt16List = [33333, 44444], " "uInt32List = [3333333333], " "uInt64List = [11111111111111111111], " "float32List = [5555.5, inf, -inf, nan], " "float64List = [7777.75, inf, -inf, nan], " "textList = [\"plugh\", \"xyzzy\", \"thud\"], " "dataList = [\"oops\", \"exhausted\", \"rfc3092\"], " "structList = [" "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"structlist 1\", " "enumField = foo, " "interfaceField = void), " "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"structlist 2\", " "enumField = foo, " "interfaceField = void), " "(" "voidField = void, " "boolField = false, " "int8Field = 0, " "int16Field = 0, " "int32Field = 0, " "int64Field = 0, " "uInt8Field = 0, " "uInt16Field = 0, " "uInt32Field = 0, " "uInt64Field = 0, " "float32Field = 0, " "float64Field = 0, " "textField = \"structlist 3\", " "enumField = foo, " "interfaceField = void)], " "enumList = [foo, garply])", kj::str(root)); } TEST(Stringify, PrettyPrint) { MallocMessageBuilder builder; auto root = builder.initRoot(); EXPECT_EQ( "( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " enumField = foo,\n" " interfaceField = void )", prettyPrint(root).flatten()); initTestMessage(root); EXPECT_EQ( "( voidField = void,\n" " boolField = true,\n" " int8Field = -123,\n" " int16Field = -12345,\n" " int32Field = -12345678,\n" " int64Field = -123456789012345,\n" " uInt8Field = 234,\n" " uInt16Field = 45678,\n" " uInt32Field = 3456789012,\n" " uInt64Field = 12345678901234567890,\n" " float32Field = 1234.5,\n" " float64Field = -1.23e47,\n" " textField = \"foo\",\n" " dataField = \"bar\",\n" " structField = (\n" " voidField = void,\n" " boolField = true,\n" " int8Field = -12,\n" " int16Field = 3456,\n" " int32Field = -78901234,\n" " int64Field = 56789012345678,\n" " uInt8Field = 90,\n" " uInt16Field = 1234,\n" " uInt32Field = 56789012,\n" " uInt64Field = 345678901234567890,\n" " float32Field = -1.25e-10,\n" " float64Field = 345,\n" " textField = \"baz\",\n" " dataField = \"qux\",\n" " structField = (\n" " voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"nested\",\n" " structField = (\n" " voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"really nested\",\n" " enumField = foo,\n" " interfaceField = void ),\n" " enumField = foo,\n" " interfaceField = void ),\n" " enumField = baz,\n" " interfaceField = void,\n" " voidList = [void, void, void],\n" " boolList = [false, true, false, true, true],\n" " int8List = [12, -34, -128, 127],\n" " int16List = [1234, -5678, -32768, 32767],\n" " int32List = [12345678, -90123456, -2147483648, 2147483647],\n" " int64List = [123456789012345, -678901234567890, " "-9223372036854775808, 9223372036854775807],\n" " uInt8List = [12, 34, 0, 255],\n" " uInt16List = [1234, 5678, 0, 65535],\n" " uInt32List = [12345678, 90123456, 0, 4294967295],\n" " uInt64List = [123456789012345, 678901234567890, 0, 18446744073709551615],\n" " float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37],\n" " float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],\n" " textList = [\"quux\", \"corge\", \"grault\"],\n" " dataList = [\"garply\", \"waldo\", \"fred\"],\n" " structList = [\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"x structlist 1\",\n" " enumField = foo,\n" " interfaceField = void ),\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"x structlist 2\",\n" " enumField = foo,\n" " interfaceField = void ),\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"x structlist 3\",\n" " enumField = foo,\n" " interfaceField = void ) ],\n" " enumList = [qux, bar, grault] ),\n" " enumField = corge,\n" " interfaceField = void,\n" " voidList = [void, void, void, void, void, void],\n" " boolList = [true, false, false, true],\n" " int8List = [111, -111],\n" " int16List = [11111, -11111],\n" " int32List = [111111111, -111111111],\n" " int64List = [1111111111111111111, -1111111111111111111],\n" " uInt8List = [111, 222],\n" " uInt16List = [33333, 44444],\n" " uInt32List = [3333333333],\n" " uInt64List = [11111111111111111111],\n" " float32List = [5555.5, inf, -inf, nan],\n" " float64List = [7777.75, inf, -inf, nan],\n" " textList = [\"plugh\", \"xyzzy\", \"thud\"],\n" " dataList = [\"oops\", \"exhausted\", \"rfc3092\"],\n" " structList = [\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"structlist 1\",\n" " enumField = foo,\n" " interfaceField = void ),\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"structlist 2\",\n" " enumField = foo,\n" " interfaceField = void ),\n" " ( voidField = void,\n" " boolField = false,\n" " int8Field = 0,\n" " int16Field = 0,\n" " int32Field = 0,\n" " int64Field = 0,\n" " uInt8Field = 0,\n" " uInt16Field = 0,\n" " uInt32Field = 0,\n" " uInt64Field = 0,\n" " float32Field = 0,\n" " float64Field = 0,\n" " textField = \"structlist 3\",\n" " enumField = foo,\n" " interfaceField = void ) ],\n" " enumList = [foo, garply] )", prettyPrint(root).flatten()); } TEST(Stringify, PrettyPrintAdvanced) { MallocMessageBuilder builder; { auto root = builder.initRoot(); auto list = root.initStructList(3); list[0].setInt32Field(123); list[0].setTextField("foo"); list[1].setInt32Field(456); list[1].setTextField("bar"); list[2].setInt32Field(789); list[2].setTextField("baz"); EXPECT_EQ( "( structList = [\n" " (int32Field = 123, textField = \"foo\"),\n" " (int32Field = 456, textField = \"bar\"),\n" " (int32Field = 789, textField = \"baz\") ] )", prettyPrint(root).flatten()); root.setSomeText("foo"); EXPECT_EQ( "( someText = \"foo\",\n" " structList = [\n" " (int32Field = 123, textField = \"foo\"),\n" " (int32Field = 456, textField = \"bar\"),\n" " (int32Field = 789, textField = \"baz\") ] )", prettyPrint(root).flatten()); } { auto root = builder.initRoot(); auto ll = root.initInt32ListList(3); ll.set(0, {123, 456, 789, 1234567890}); ll.set(1, {234, 567, 891, 1234567890}); ll.set(2, {345, 678, 912, 1234567890}); EXPECT_EQ( "[ [123, 456, 789, 1234567890],\n" " [234, 567, 891, 1234567890],\n" " [345, 678, 912, 1234567890] ]", prettyPrint(ll).flatten()); EXPECT_EQ( "( int32ListList = [\n" " [123, 456, 789, 1234567890],\n" " [234, 567, 891, 1234567890],\n" " [345, 678, 912, 1234567890] ] )", prettyPrint(root).flatten()); root.initList8(0); EXPECT_EQ( "( list8 = [],\n" " int32ListList = [\n" " [123, 456, 789, 1234567890],\n" " [234, 567, 891, 1234567890],\n" " [345, 678, 912, 1234567890] ] )", prettyPrint(root).flatten()); auto l8 = root.initList8(1); l8[0].setF(12); EXPECT_EQ( "( list8 = [(f = 12)],\n" " int32ListList = [\n" " [123, 456, 789, 1234567890],\n" " [234, 567, 891, 1234567890],\n" " [345, 678, 912, 1234567890] ] )", prettyPrint(root).flatten()); l8 = root.initList8(2); l8[0].setF(12); l8[1].setF(34); EXPECT_EQ( "( list8 = [(f = 12), (f = 34)],\n" " int32ListList = [\n" " [123, 456, 789, 1234567890],\n" " [234, 567, 891, 1234567890],\n" " [345, 678, 912, 1234567890] ] )", prettyPrint(root).flatten()); } { auto root = builder.initRoot(); auto s = root.getUn().initStruct(); EXPECT_EQ( "(un = (struct = ()))", prettyPrint(root).flatten()); s.setSomeText("foo"); EXPECT_EQ( "( un = (\n" " struct = (someText = \"foo\") ) )", prettyPrint(root).flatten()); s.setMoreText("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar"); EXPECT_EQ( "( un = (\n" " struct = (\n" " someText = \"foo\",\n" " moreText = \"baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\" ) ) )", prettyPrint(root).flatten()); } } TEST(Stringify, Unions) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getUnion0().setU0f0s16(123); root.getUnion1().setU1f0sp("foo"); root.getUnion2().setU2f0s1(true); root.getUnion3().setU3f0s64(123456789012345678ll); EXPECT_EQ("(" "union0 = (u0f0s16 = 123), " "union1 = (u1f0sp = \"foo\"), " "union2 = (u2f0s1 = true), " "union3 = (u3f0s64 = 123456789012345678), " "bit0 = false, bit2 = false, bit3 = false, bit4 = false, bit5 = false, " "bit6 = false, bit7 = false, byte0 = 0)", kj::str(root)); EXPECT_EQ("(u0f0s16 = 123)", kj::str(root.getUnion0())); EXPECT_EQ("(u1f0sp = \"foo\")", kj::str(root.getUnion1())); EXPECT_EQ("(u2f0s1 = true)", kj::str(root.getUnion2())); EXPECT_EQ("(u3f0s64 = 123456789012345678)", kj::str(root.getUnion3())); } TEST(Stringify, UnionDefaults) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.getUnion0().setU0f0s16(0); // Non-default field has default value. root.getUnion1().setU1f0sp("foo"); // Non-default field has non-default value. root.getUnion2().setU2f0s1(false); // Default field has default value. root.getUnion3().setU3f0s1(true); // Default field has non-default value. EXPECT_EQ("(" "union0 = (u0f0s16 = 0), " "union1 = (u1f0sp = \"foo\"), " "union2 = (u2f0s1 = false), " "union3 = (u3f0s1 = true), " "bit0 = false, bit2 = false, bit3 = false, bit4 = false, bit5 = false, " "bit6 = false, bit7 = false, byte0 = 0)", kj::str(root)); EXPECT_EQ("(u0f0s16 = 0)", kj::str(root.getUnion0())); EXPECT_EQ("(u1f0sp = \"foo\")", kj::str(root.getUnion1())); EXPECT_EQ("(u2f0s1 = false)", kj::str(root.getUnion2())); EXPECT_EQ("(u3f0s1 = true)", kj::str(root.getUnion3())); } TEST(Stringify, UnnamedUnions) { MallocMessageBuilder builder; auto root = builder.initRoot(); root.setBar(123); EXPECT_EQ("(middle = 0, bar = 123)", kj::str(root)); EXPECT_EQ("(middle = 0, bar = 123)", prettyPrint(root).flatten()); root.setAfter("foooooooooooooooooooooooooooooooo"); EXPECT_EQ("(middle = 0, bar = 123, after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root)); EXPECT_EQ( "( middle = 0,\n" " bar = 123,\n" " after = \"foooooooooooooooooooooooooooooooo\" )", prettyPrint(root).flatten()); root.setBefore("before"); EXPECT_EQ("(before = \"before\", middle = 0, bar = 123, " "after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root)); EXPECT_EQ( "( before = \"before\",\n" " middle = 0,\n" " bar = 123,\n" " after = \"foooooooooooooooooooooooooooooooo\" )", prettyPrint(root).flatten()); root.setFoo(0); EXPECT_EQ( "(before = \"before\", foo = 0, middle = 0, after = \"foooooooooooooooooooooooooooooooo\")", kj::str(root)); EXPECT_EQ( "( before = \"before\",\n" " foo = 0,\n" " middle = 0,\n" " after = \"foooooooooooooooooooooooooooooooo\" )", prettyPrint(root).flatten()); } TEST(Stringify, StructUnions) { MallocMessageBuilder builder; auto root = builder.initRoot(); auto s = root.getUn().initStruct(); s.setSomeText("foo"); s.setMoreText("bar"); EXPECT_EQ("(un = (struct = (someText = \"foo\", moreText = \"bar\")))", kj::str(root)); } TEST(Stringify, MoreValues) { EXPECT_EQ("123", kj::str(DynamicValue::Reader(123))); EXPECT_EQ("1.23e47", kj::str(DynamicValue::Reader(123e45))); EXPECT_EQ("\"foo\"", kj::str(DynamicValue::Reader("foo"))); EXPECT_EQ("\"\\a\\b\\n\\t\\\"\"", kj::str(DynamicValue::Reader("\a\b\n\t\""))); EXPECT_EQ("foo", kj::str(DynamicValue::Reader(TestEnum::FOO))); EXPECT_EQ("(123)", kj::str(DynamicValue::Reader(static_cast(123)))); } TEST(Stringify, Generics) { MallocMessageBuilder builder; auto root = builder.initRoot>::Inner>(); root.setFoo("abcd"); auto l = root.initBar(2); l.set(0, 123); l.set(1, 456); EXPECT_EQ("(foo = \"abcd\", bar = [123, 456])", kj::str(root)); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize-text.h0000644000175000017500000000703514527152321021763 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Philip Quinn. // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include "dynamic.h" #include "orphan.h" #include "schema.h" CAPNP_BEGIN_HEADER namespace capnp { class TextCodec { // Reads and writes Cap'n Proto objects in a plain text format (as used in the schema // language for constants, and read/written by the 'decode' and 'encode' commands of // the capnp tool). // // This format is useful for debugging or human input, but it is not a robust alternative // to the binary format. Changes to a schema's types or names that are permitted in a // schema's binary evolution will likely break messages stored in this format. // // Note that definitions or references (to constants, other fields, or files) are not // permitted in this format. To evaluate declarations with the full expressiveness of the // schema language, see `capnp::SchemaParser`. // // Requires linking with the capnpc library. public: TextCodec(); ~TextCodec() noexcept(true); void setPrettyPrint(bool enabled); // If enabled, pads the output of `encode()` with spaces and newlines to make it more // human-readable. template kj::String encode(T&& value) const; kj::String encode(DynamicValue::Reader value) const; // Encode any Cap'n Proto value. template Orphan decode(kj::StringPtr input, Orphanage orphanage) const; // Decode a text message into a Cap'n Proto object of type T, allocated in the given // orphanage. Any errors parsing the input or assigning the fields of T are thrown as // exceptions. void decode(kj::StringPtr input, DynamicStruct::Builder output) const; // Decode a text message for a struct into the given builder. Any errors parsing the // input or assigning the fields of the output are thrown as exceptions. // TODO(someday): expose some control over the error handling? private: Orphan decode(kj::StringPtr input, Type type, Orphanage orphanage) const; bool prettyPrint; }; // ======================================================================================= // inline stuff template inline kj::String TextCodec::encode(T&& value) const { return encode(DynamicValue::Reader(ReaderFor>(kj::fwd(value)))); } template inline Orphan TextCodec::decode(kj::StringPtr input, Orphanage orphanage) const { return decode(input, Type::from(), orphanage).template releaseAs(); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/list.c++0000644000175000017500000000234114527152321020101 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "list.h" namespace capnp { } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema.h0000644000175000017500000011610614712011043020241 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #if CAPNP_LITE #error "Reflection APIs, including this header, are not available in lite mode." #endif #undef CONST // For some ridiculous reason, Windows defines CONST to const. We have an enum value called CONST // in schema.capnp.h, so if this is defined, compilation is gonna fail. So we undef it because // that seems strictly better than failing entirely. But this could cause trouble for people later // on if they, say, include windows.h, then include schema.h, then include another windows API // header that uses CONST. I suppose they may have to re-#define CONST in between, or change the // header ordering. Sorry. // // Please don't file a bug report telling us to change our enum naming style. You are at least // seven years too late. #include #include #include // work-around macro conflict with `VOID` CAPNP_BEGIN_HEADER namespace capnp { class Schema; class StructSchema; class EnumSchema; class InterfaceSchema; class ConstSchema; class ListSchema; class Type; template ()> struct SchemaType_ { typedef Schema Type; }; template struct SchemaType_ { typedef schema::Type::Which Type; }; template struct SchemaType_ { typedef schema::Type::Which Type; }; template struct SchemaType_ { typedef EnumSchema Type; }; template struct SchemaType_ { typedef StructSchema Type; }; template struct SchemaType_ { typedef InterfaceSchema Type; }; template struct SchemaType_ { typedef ListSchema Type; }; template using SchemaType = typename SchemaType_::Type; // SchemaType is the type of T's schema, e.g. StructSchema if T is a struct. namespace _ { // private extern const RawSchema NULL_SCHEMA; extern const RawSchema NULL_STRUCT_SCHEMA; extern const RawSchema NULL_ENUM_SCHEMA; extern const RawSchema NULL_INTERFACE_SCHEMA; extern const RawSchema NULL_CONST_SCHEMA; // The schema types default to these null (empty) schemas in case of error, especially when // exceptions are disabled. } // namespace _ (private) class Schema { // Convenience wrapper around capnp::schema::Node. public: inline Schema(): raw(&_::NULL_SCHEMA.defaultBrand) {} template static inline SchemaType from() { return SchemaType::template fromImpl(); } // Get the Schema for a particular compiled-in type. schema::Node::Reader getProto() const; // Get the underlying Cap'n Proto representation of the schema node. (Note that this accessor // has performance comparable to accessors of struct-typed fields on Reader classes.) kj::ArrayPtr asUncheckedMessage() const; // Get the encoded schema node content as a single message segment. It is safe to read as an // unchecked message. Schema getDependency(uint64_t id) const CAPNP_DEPRECATED("Does not handle generics correctly."); // DEPRECATED: This method cannot correctly account for generic type parameter bindings that // may apply to the dependency. Instead of using this method, use a method of the Schema API // that corresponds to the exact kind of dependency. For example, to get a field type, use // StructSchema::Field::getType(). // // Gets the Schema for one of this Schema's dependencies. For example, if this Schema is for a // struct, you could look up the schema for one of its fields' types. Throws an exception if this // schema doesn't actually depend on the given id. // // Note that not all type IDs found in the schema node are considered "dependencies" -- only the // ones that are needed to implement the dynamic API are. That includes: // - Field types. // - Group types. // - scopeId for group nodes, but NOT otherwise. // - Method parameter and return types. // // The following are NOT considered dependencies: // - Nested nodes. // - scopeId for a non-group node. // - Annotations. // // To obtain schemas for those, you would need a SchemaLoader. bool isBranded() const; // Returns true if this schema represents a non-default parameterization of this type. Schema getGeneric() const; // Get the version of this schema with any brands removed. class BrandArgumentList; BrandArgumentList getBrandArgumentsAtScope(uint64_t scopeId) const; // Gets the values bound to the brand parameters at the given scope. kj::Array getGenericScopeIds() const; // Returns the type IDs of all parent scopes that have generic parameters, to which this type is // subject. StructSchema asStruct() const; EnumSchema asEnum() const; InterfaceSchema asInterface() const; ConstSchema asConst() const; // Cast the Schema to a specific type. Throws an exception if the type doesn't match. Use // getProto() to determine type, e.g. getProto().isStruct(). inline bool operator==(const Schema& other) const { return raw == other.raw; } inline bool operator!=(const Schema& other) const { return raw != other.raw; } // Determine whether two Schemas are wrapping the exact same underlying data, by identity. If // you want to check if two Schemas represent the same type (but possibly different versions of // it), compare their IDs instead. inline uint hashCode() const { return kj::hashCode(raw); } template void requireUsableAs() const; // Throws an exception if a value with this Schema cannot safely be cast to a native value of // the given type. This passes if either: // - *this == from() // - This schema was loaded with SchemaLoader, the type ID matches typeId(), and // loadCompiledTypeAndDependencies() was called on the SchemaLoader. kj::StringPtr getShortDisplayName() const; // Get the short version of the node's display name. const kj::StringPtr getUnqualifiedName() const; // Get the display name "nickname" of this node minus the prefix private: const _::RawBrandedSchema* raw; inline explicit Schema(const _::RawBrandedSchema* raw): raw(raw) { KJ_IREQUIRE(raw->lazyInitializer == nullptr, "Must call ensureInitialized() on RawSchema before constructing Schema."); } template static inline Schema fromImpl() { return Schema(&_::rawSchema()); } void requireUsableAs(const _::RawSchema* expected) const; uint32_t getSchemaOffset(const schema::Value::Reader& value) const; Type getBrandBinding(uint64_t scopeId, uint index) const; // Look up the binding for a brand parameter used by this Schema. Returns `AnyPointer` if the // parameter is not bound. // // TODO(someday): Public interface for iterating over all bindings? Schema getDependency(uint64_t id, uint location) const; // Look up schema for a particular dependency of this schema. `location` is the dependency // location number as defined in _::RawBrandedSchema. Type interpretType(schema::Type::Reader proto, uint location) const; // Interpret a schema::Type in the given location within the schema, compiling it into a // Type object. friend class StructSchema; friend class EnumSchema; friend class InterfaceSchema; friend class ConstSchema; friend class ListSchema; friend class SchemaLoader; friend class Type; friend kj::StringTree _::structString( _::StructReader reader, const _::RawBrandedSchema& schema); friend kj::String _::enumString(uint16_t value, const _::RawBrandedSchema& schema); }; kj::StringPtr KJ_STRINGIFY(const Schema& schema); class Schema::BrandArgumentList { // A list of generic parameter bindings for parameters of some particular type. Note that since // parameters on an outer type apply to all inner types as well, a deeply-nested type can have // multiple BrandArgumentLists that apply to it. // // A BrandArgumentList only represents the arguments that the client of the type specified. Since // new parameters can be added over time, this list may not cover all defined parameters for the // type. Missing parameters should be treated as AnyPointer. This class's implementation of // operator[] already does this for you; out-of-bounds access will safely return AnyPointer. public: inline BrandArgumentList(): scopeId(0), size_(0), bindings(nullptr) {} inline uint size() const { return size_; } Type operator[](uint index) const; typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: uint64_t scopeId; uint size_; bool isUnbound; const _::RawBrandedSchema::Binding* bindings; inline BrandArgumentList(uint64_t scopeId, bool isUnbound) : scopeId(scopeId), size_(0), isUnbound(isUnbound), bindings(nullptr) {} inline BrandArgumentList(uint64_t scopeId, uint size, const _::RawBrandedSchema::Binding* bindings) : scopeId(scopeId), size_(size), isUnbound(false), bindings(bindings) {} friend class Schema; }; // ------------------------------------------------------------------- class StructSchema: public Schema { public: inline StructSchema(): Schema(&_::NULL_STRUCT_SCHEMA.defaultBrand) {} class Field; class FieldList; class FieldSubset; FieldList getFields() const; // List top-level fields of this struct. This list will contain top-level groups (including // named unions) but not the members of those groups. The list does, however, contain the // members of the unnamed union, if there is one. FieldSubset getUnionFields() const; // If the field contains an unnamed union, get a list of fields in the union, ordered by // ordinal. Since discriminant values are assigned sequentially by ordinal, you may index this // list by discriminant value. FieldSubset getNonUnionFields() const; // Get the fields of this struct which are not in an unnamed union, ordered by ordinal. kj::Maybe findFieldByName(kj::StringPtr name) const; // Find the field with the given name, or return null if there is no such field. If the struct // contains an unnamed union, then this will find fields of that union in addition to fields // of the outer struct, since they exist in the same namespace. It will not, however, find // members of groups (including named unions) -- you must first look up the group itself, // then dig into its type. Field getFieldByName(kj::StringPtr name) const; // Like findFieldByName() but throws an exception on failure. kj::Maybe getFieldByDiscriminant(uint16_t discriminant) const; // Finds the field whose `discriminantValue` is equal to the given value, or returns null if // there is no such field. (If the schema does not represent a union or a struct containing // an unnamed union, then this always returns null.) bool isStreamResult() const; // Convenience method to check if this is the result type of a streaming RPC method. bool mayContainCapabilities() const { return raw->generic->mayContainCapabilities; } // Returns true if a struct of this type may transitively contain any capabilities. I.e., are // any of the fields an interface type, or a struct type that may in turn contain capabilities? // // This is meant for optimizations where various bookkeeping can possibly be skipped if it is // known in advance that there are no capabilities. Note that this may conservatively return true // spuriously, e.g. if it would be inconvenient to compute the correct answer. A false positive // should never cause incorrect behavior, just potentially hurt performance. // // It's important to keep in mind that even if a schema has no capability-typed fields today, // they could always be added in future versions of the schema. So, just because the schema // doesn't contain capabilities does NOT necessarily mean that an instance of the struct can't // contain capabilities. However, it is a pretty good hint that the application won't plan to // use such capabilities -- for example, if there are no caps in an RPC call's response type // according to the client's version of the schema, then the client clearly isn't going to try // to make any pipelined calls. The server could be operating with a new version of the schema // and could actually return capabilities, but for the client to make a pipelined call, the // client would have to know in advance that capabilities could be returned. private: StructSchema(Schema base): Schema(base) {} template static inline StructSchema fromImpl() { return StructSchema(Schema(&_::rawBrandedSchema())); } friend class Schema; friend class Type; }; class StructSchema::Field { public: Field() = default; inline schema::Field::Reader getProto() const { return proto; } inline StructSchema getContainingStruct() const { return parent; } inline uint getIndex() const { return index; } // Get the index of this field within the containing struct or union. Type getType() const; // Get the type of this field. Note that this is preferred over getProto().getType() as this // method will apply generics. uint32_t getDefaultValueSchemaOffset() const; // For struct, list, and object fields, returns the offset, in words, within the first segment of // the struct's schema, where this field's default value pointer is located. The schema is // always stored as a single-segment unchecked message, which in turn means that the default // value pointer itself can be treated as the root of an unchecked message -- if you know where // to find it, which is what this method helps you with. // // For blobs, returns the offset of the beginning of the blob's content within the first segment // of the struct's schema. // // This is primarily useful for code generators. The C++ code generator, for example, embeds // the entire schema as a raw word array within the generated code. Of course, to implement // field accessors, it needs access to those fields' default values. Embedding separate copies // of those default values would be redundant since they are already included in the schema, but // seeking through the schema at runtime to find the default values would be ugly. Instead, // the code generator can use getDefaultValueSchemaOffset() to find the offset of the default // value within the schema, and can simply apply that offset at runtime. // // If the above does not make sense, you probably don't need this method. inline bool operator==(const Field& other) const; inline bool operator!=(const Field& other) const { return !(*this == other); } inline uint hashCode() const; private: StructSchema parent; uint index; schema::Field::Reader proto; inline Field(StructSchema parent, uint index, schema::Field::Reader proto) : parent(parent), index(index), proto(proto) {} friend class StructSchema; }; kj::StringPtr KJ_STRINGIFY(const StructSchema::Field& field); class StructSchema::FieldList { public: FieldList() = default; // empty list inline uint size() const { return list.size(); } inline Field operator[](uint index) const { return Field(parent, index, list[index]); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: StructSchema parent; List::Reader list; inline FieldList(StructSchema parent, List::Reader list) : parent(parent), list(list) {} friend class StructSchema; }; class StructSchema::FieldSubset { public: FieldSubset() = default; // empty list inline uint size() const { return size_; } inline Field operator[](uint index) const { return Field(parent, indices[index], list[indices[index]]); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: StructSchema parent; List::Reader list; const uint16_t* indices; uint size_; inline FieldSubset(StructSchema parent, List::Reader list, const uint16_t* indices, uint size) : parent(parent), list(list), indices(indices), size_(size) {} friend class StructSchema; }; // ------------------------------------------------------------------- class EnumSchema: public Schema { public: inline EnumSchema(): Schema(&_::NULL_ENUM_SCHEMA.defaultBrand) {} class Enumerant; class EnumerantList; EnumerantList getEnumerants() const; kj::Maybe findEnumerantByName(kj::StringPtr name) const; Enumerant getEnumerantByName(kj::StringPtr name) const; // Like findEnumerantByName() but throws an exception on failure. private: EnumSchema(Schema base): Schema(base) {} template static inline EnumSchema fromImpl() { return EnumSchema(Schema(&_::rawBrandedSchema())); } friend class Schema; friend class Type; }; class EnumSchema::Enumerant { public: Enumerant() = default; inline schema::Enumerant::Reader getProto() const { return proto; } inline EnumSchema getContainingEnum() const { return parent; } inline uint16_t getOrdinal() const { return ordinal; } inline uint getIndex() const { return ordinal; } inline bool operator==(const Enumerant& other) const; inline bool operator!=(const Enumerant& other) const { return !(*this == other); } inline uint hashCode() const; private: EnumSchema parent; uint16_t ordinal; schema::Enumerant::Reader proto; inline Enumerant(EnumSchema parent, uint16_t ordinal, schema::Enumerant::Reader proto) : parent(parent), ordinal(ordinal), proto(proto) {} friend class EnumSchema; }; class EnumSchema::EnumerantList { public: EnumerantList() = default; // empty list inline uint size() const { return list.size(); } inline Enumerant operator[](uint index) const { return Enumerant(parent, index, list[index]); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: EnumSchema parent; List::Reader list; inline EnumerantList(EnumSchema parent, List::Reader list) : parent(parent), list(list) {} friend class EnumSchema; }; // ------------------------------------------------------------------- class InterfaceSchema: public Schema { public: inline InterfaceSchema(): Schema(&_::NULL_INTERFACE_SCHEMA.defaultBrand) {} class Method; class MethodList; MethodList getMethods() const; kj::Maybe findMethodByName(kj::StringPtr name) const; Method getMethodByName(kj::StringPtr name) const; // Like findMethodByName() but throws an exception on failure. class SuperclassList; SuperclassList getSuperclasses() const; // Get the immediate superclasses of this type, after applying generics. bool extends(InterfaceSchema other) const; // Returns true if `other` is a superclass of this interface (including if `other == *this`). kj::Maybe findSuperclass(uint64_t typeId) const; // Find the superclass of this interface with the given type ID. Returns null if the interface // extends no such type. private: InterfaceSchema(Schema base): Schema(base) {} template static inline InterfaceSchema fromImpl() { return InterfaceSchema(Schema(&_::rawBrandedSchema())); } friend class Schema; friend class Type; kj::Maybe findMethodByName(kj::StringPtr name, uint& counter) const; bool extends(InterfaceSchema other, uint& counter) const; kj::Maybe findSuperclass(uint64_t typeId, uint& counter) const; // We protect against malicious schemas with large or cyclic hierarchies by cutting off the // search when the counter reaches a threshold. }; class InterfaceSchema::Method { public: Method() = default; inline schema::Method::Reader getProto() const { return proto; } inline InterfaceSchema getContainingInterface() const { return parent; } inline uint16_t getOrdinal() const { return ordinal; } inline uint getIndex() const { return ordinal; } bool isStreaming() const { return getResultType().isStreamResult(); } // Check if this is a streaming method. StructSchema getParamType() const; StructSchema getResultType() const; // Get the parameter and result types, including substituting generic parameters. inline bool operator==(const Method& other) const; inline bool operator!=(const Method& other) const { return !(*this == other); } inline uint hashCode() const; private: InterfaceSchema parent; uint16_t ordinal; schema::Method::Reader proto; inline Method(InterfaceSchema parent, uint16_t ordinal, schema::Method::Reader proto) : parent(parent), ordinal(ordinal), proto(proto) {} friend class InterfaceSchema; }; class InterfaceSchema::MethodList { public: MethodList() = default; // empty list inline uint size() const { return list.size(); } inline Method operator[](uint index) const { return Method(parent, index, list[index]); } typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: InterfaceSchema parent; List::Reader list; inline MethodList(InterfaceSchema parent, List::Reader list) : parent(parent), list(list) {} friend class InterfaceSchema; }; class InterfaceSchema::SuperclassList { public: SuperclassList() = default; // empty list inline uint size() const { return list.size(); } InterfaceSchema operator[](uint index) const; typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: InterfaceSchema parent; List::Reader list; inline SuperclassList(InterfaceSchema parent, List::Reader list) : parent(parent), list(list) {} friend class InterfaceSchema; }; // ------------------------------------------------------------------- class ConstSchema: public Schema { // Represents a constant declaration. // // `ConstSchema` can be implicitly cast to DynamicValue to read its value. public: inline ConstSchema(): Schema(&_::NULL_CONST_SCHEMA.defaultBrand) {} template ReaderFor as() const; // Read the constant's value. This is a convenience method equivalent to casting the ConstSchema // to a DynamicValue and then calling its `as()` method. For dependency reasons, this method // is defined in , which you must #include explicitly. uint32_t getValueSchemaOffset() const; // Much like StructSchema::Field::getDefaultValueSchemaOffset(), if the constant has pointer // type, this gets the offset from the beginning of the constant's schema node to a pointer // representing the constant value. Type getType() const; private: ConstSchema(Schema base): Schema(base) {} friend class Schema; }; // ------------------------------------------------------------------- class Type { public: struct BrandParameter { uint64_t scopeId; uint index; }; struct ImplicitParameter { uint index; }; inline Type(); inline Type(schema::Type::Which primitive); inline Type(StructSchema schema); inline Type(EnumSchema schema); inline Type(InterfaceSchema schema); inline Type(ListSchema schema); inline Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind); inline Type(BrandParameter param); inline Type(ImplicitParameter param); template inline static Type from(); template inline static Type from(T&& value); inline schema::Type::Which which() const; StructSchema asStruct() const; EnumSchema asEnum() const; InterfaceSchema asInterface() const; ListSchema asList() const; // Each of these methods may only be called if which() returns the corresponding type. kj::Maybe getBrandParameter() const; // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular // AnyPointer and not a parameter. kj::Maybe getImplicitParameter() const; // Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular // AnyPointer and not a parameter. "Implicit parameters" refer to type parameters on methods. inline schema::Type::AnyPointer::Unconstrained::Which whichAnyPointerKind() const; // Only callable if which() returns ANY_POINTER. inline bool isVoid() const; inline bool isBool() const; inline bool isInt8() const; inline bool isInt16() const; inline bool isInt32() const; inline bool isInt64() const; inline bool isUInt8() const; inline bool isUInt16() const; inline bool isUInt32() const; inline bool isUInt64() const; inline bool isFloat32() const; inline bool isFloat64() const; inline bool isText() const; inline bool isData() const; inline bool isList() const; inline bool isEnum() const; inline bool isStruct() const; inline bool isInterface() const; inline bool isAnyPointer() const; bool operator==(const Type& other) const; inline bool operator!=(const Type& other) const { return !(*this == other); } uint hashCode() const; inline Type wrapInList(uint depth = 1) const; // Return the Type formed by wrapping this type in List() `depth` times. inline Type(schema::Type::Which derived, const _::RawBrandedSchema* schema); // For internal use. private: schema::Type::Which baseType; // type not including applications of List() uint8_t listDepth; // 0 for T, 1 for List(T), 2 for List(List(T)), ... bool isImplicitParam; // If true, this refers to an implicit method parameter. baseType must be ANY_POINTER, scopeId // must be zero, and paramIndex indicates the parameter index. union { uint16_t paramIndex; // If baseType is ANY_POINTER but this Type actually refers to a type parameter, this is the // index of the parameter among the parameters at its scope, and `scopeId` below is the type ID // of the scope where the parameter was defined. schema::Type::AnyPointer::Unconstrained::Which anyPointerKind; // If scopeId is zero and isImplicitParam is false. }; union { const _::RawBrandedSchema* schema; // if type is struct, enum, interface... uint64_t scopeId; // if type is AnyPointer but it's actually a type parameter... }; Type(schema::Type::Which baseType, uint8_t listDepth, const _::RawBrandedSchema* schema) : baseType(baseType), listDepth(listDepth), schema(schema) { KJ_IREQUIRE(baseType != schema::Type::ANY_POINTER); } void requireUsableAs(Type expected) const; template struct FromValueImpl; friend class ListSchema; // only for requireUsableAs() }; // ------------------------------------------------------------------- class ListSchema { // ListSchema is a little different because list types are not described by schema nodes. So, // ListSchema doesn't subclass Schema. public: ListSchema() = default; static ListSchema of(schema::Type::Which primitiveType); static ListSchema of(StructSchema elementType); static ListSchema of(EnumSchema elementType); static ListSchema of(InterfaceSchema elementType); static ListSchema of(ListSchema elementType); static ListSchema of(Type elementType); // Construct the schema for a list of the given type. static ListSchema of(schema::Type::Reader elementType, Schema context) CAPNP_DEPRECATED("Does not handle generics correctly."); // DEPRECATED: This method cannot correctly account for generic type parameter bindings that // may apply to the input type. Instead of using this method, use a method of the Schema API // that corresponds to the exact kind of dependency. For example, to get a field type, use // StructSchema::Field::getType(). // // Construct from an element type schema. Requires a context which can handle getDependency() // requests for any type ID found in the schema. Type getElementType() const; inline schema::Type::Which whichElementType() const; // Get the element type's "which()". ListSchema does not actually store a schema::Type::Reader // describing the element type, but if it did, this would be equivalent to calling // .getBody().which() on that type. StructSchema getStructElementType() const; EnumSchema getEnumElementType() const; InterfaceSchema getInterfaceElementType() const; ListSchema getListElementType() const; // Get the schema for complex element types. Each of these throws an exception if the element // type is not of the requested kind. inline bool operator==(const ListSchema& other) const { return elementType == other.elementType; } inline bool operator!=(const ListSchema& other) const { return elementType != other.elementType; } template void requireUsableAs() const; private: Type elementType; inline explicit ListSchema(Type elementType): elementType(elementType) {} template struct FromImpl; template static inline ListSchema fromImpl() { return FromImpl::get(); } void requireUsableAs(ListSchema expected) const; friend class Schema; }; // ======================================================================================= // inline implementation template <> inline schema::Type::Which Schema::from() { return schema::Type::VOID; } template <> inline schema::Type::Which Schema::from() { return schema::Type::BOOL; } template <> inline schema::Type::Which Schema::from() { return schema::Type::INT8; } template <> inline schema::Type::Which Schema::from() { return schema::Type::INT16; } template <> inline schema::Type::Which Schema::from() { return schema::Type::INT32; } template <> inline schema::Type::Which Schema::from() { return schema::Type::INT64; } template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT8; } template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT16; } template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT32; } template <> inline schema::Type::Which Schema::from() { return schema::Type::UINT64; } template <> inline schema::Type::Which Schema::from() { return schema::Type::FLOAT32; } template <> inline schema::Type::Which Schema::from() { return schema::Type::FLOAT64; } template <> inline schema::Type::Which Schema::from() { return schema::Type::TEXT; } template <> inline schema::Type::Which Schema::from() { return schema::Type::DATA; } inline Schema Schema::getDependency(uint64_t id) const { return getDependency(id, 0); } inline bool Schema::isBranded() const { return raw != &raw->generic->defaultBrand; } inline Schema Schema::getGeneric() const { return Schema(&raw->generic->defaultBrand); } template inline void Schema::requireUsableAs() const { requireUsableAs(&_::rawSchema()); } inline bool StructSchema::Field::operator==(const Field& other) const { return parent == other.parent && index == other.index; } inline bool EnumSchema::Enumerant::operator==(const Enumerant& other) const { return parent == other.parent && ordinal == other.ordinal; } inline bool InterfaceSchema::Method::operator==(const Method& other) const { return parent == other.parent && ordinal == other.ordinal; } inline uint StructSchema::Field::hashCode() const { return kj::hashCode(parent, index); } inline uint EnumSchema::Enumerant::hashCode() const { return kj::hashCode(parent, ordinal); } inline uint InterfaceSchema::Method::hashCode() const { return kj::hashCode(parent, ordinal); } inline ListSchema ListSchema::of(StructSchema elementType) { return ListSchema(Type(elementType)); } inline ListSchema ListSchema::of(EnumSchema elementType) { return ListSchema(Type(elementType)); } inline ListSchema ListSchema::of(InterfaceSchema elementType) { return ListSchema(Type(elementType)); } inline ListSchema ListSchema::of(ListSchema elementType) { return ListSchema(Type(elementType)); } inline ListSchema ListSchema::of(Type elementType) { return ListSchema(elementType); } inline Type ListSchema::getElementType() const { return elementType; } inline schema::Type::Which ListSchema::whichElementType() const { return elementType.which(); } inline StructSchema ListSchema::getStructElementType() const { return elementType.asStruct(); } inline EnumSchema ListSchema::getEnumElementType() const { return elementType.asEnum(); } inline InterfaceSchema ListSchema::getInterfaceElementType() const { return elementType.asInterface(); } inline ListSchema ListSchema::getListElementType() const { return elementType.asList(); } template inline void ListSchema::requireUsableAs() const { static_assert(kind() == Kind::LIST, "ListSchema::requireUsableAs() requires T is a list type."); requireUsableAs(Schema::from()); } inline void ListSchema::requireUsableAs(ListSchema expected) const { elementType.requireUsableAs(expected.elementType); } template struct ListSchema::FromImpl> { static inline ListSchema get() { return of(Schema::from()); } }; inline Type::Type(): baseType(schema::Type::VOID), listDepth(0), schema(nullptr) {} inline Type::Type(schema::Type::Which primitive) : baseType(primitive), listDepth(0), isImplicitParam(false) { KJ_IREQUIRE(primitive != schema::Type::STRUCT && primitive != schema::Type::ENUM && primitive != schema::Type::INTERFACE && primitive != schema::Type::LIST); if (primitive == schema::Type::ANY_POINTER) { scopeId = 0; anyPointerKind = schema::Type::AnyPointer::Unconstrained::ANY_KIND; } else { schema = nullptr; } } inline Type::Type(schema::Type::Which derived, const _::RawBrandedSchema* schema) : baseType(derived), listDepth(0), isImplicitParam(false), schema(schema) { KJ_IREQUIRE(derived == schema::Type::STRUCT || derived == schema::Type::ENUM || derived == schema::Type::INTERFACE); } inline Type::Type(StructSchema schema) : baseType(schema::Type::STRUCT), listDepth(0), schema(schema.raw) {} inline Type::Type(EnumSchema schema) : baseType(schema::Type::ENUM), listDepth(0), schema(schema.raw) {} inline Type::Type(InterfaceSchema schema) : baseType(schema::Type::INTERFACE), listDepth(0), schema(schema.raw) {} inline Type::Type(ListSchema schema) : Type(schema.getElementType()) { ++listDepth; } inline Type::Type(schema::Type::AnyPointer::Unconstrained::Which anyPointerKind) : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false), anyPointerKind(anyPointerKind), scopeId(0) {} inline Type::Type(BrandParameter param) : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false), paramIndex(param.index), scopeId(param.scopeId) {} inline Type::Type(ImplicitParameter param) : baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(true), paramIndex(param.index), scopeId(0) {} inline schema::Type::Which Type::which() const { return listDepth > 0 ? schema::Type::LIST : baseType; } inline schema::Type::AnyPointer::Unconstrained::Which Type::whichAnyPointerKind() const { KJ_IREQUIRE(baseType == schema::Type::ANY_POINTER); return !isImplicitParam && scopeId == 0 ? anyPointerKind : schema::Type::AnyPointer::Unconstrained::ANY_KIND; } template inline Type Type::from() { return Type(Schema::from()); } template struct Type::FromValueImpl { template static inline Type type(U&& value) { return Type::from(); } }; template struct Type::FromValueImpl { template static inline Type type(U&& value) { // All dynamic types have getSchema(). return value.getSchema(); } }; template inline Type Type::from(T&& value) { typedef FromAny> Base; return Type::FromValueImpl()>::type(kj::fwd(value)); } inline bool Type::isVoid () const { return baseType == schema::Type::VOID && listDepth == 0; } inline bool Type::isBool () const { return baseType == schema::Type::BOOL && listDepth == 0; } inline bool Type::isInt8 () const { return baseType == schema::Type::INT8 && listDepth == 0; } inline bool Type::isInt16 () const { return baseType == schema::Type::INT16 && listDepth == 0; } inline bool Type::isInt32 () const { return baseType == schema::Type::INT32 && listDepth == 0; } inline bool Type::isInt64 () const { return baseType == schema::Type::INT64 && listDepth == 0; } inline bool Type::isUInt8 () const { return baseType == schema::Type::UINT8 && listDepth == 0; } inline bool Type::isUInt16 () const { return baseType == schema::Type::UINT16 && listDepth == 0; } inline bool Type::isUInt32 () const { return baseType == schema::Type::UINT32 && listDepth == 0; } inline bool Type::isUInt64 () const { return baseType == schema::Type::UINT64 && listDepth == 0; } inline bool Type::isFloat32() const { return baseType == schema::Type::FLOAT32 && listDepth == 0; } inline bool Type::isFloat64() const { return baseType == schema::Type::FLOAT64 && listDepth == 0; } inline bool Type::isText () const { return baseType == schema::Type::TEXT && listDepth == 0; } inline bool Type::isData () const { return baseType == schema::Type::DATA && listDepth == 0; } inline bool Type::isList () const { return listDepth > 0; } inline bool Type::isEnum () const { return baseType == schema::Type::ENUM && listDepth == 0; } inline bool Type::isStruct () const { return baseType == schema::Type::STRUCT && listDepth == 0; } inline bool Type::isInterface() const { return baseType == schema::Type::INTERFACE && listDepth == 0; } inline bool Type::isAnyPointer() const { return baseType == schema::Type::ANY_POINTER && listDepth == 0; } inline Type Type::wrapInList(uint depth) const { Type result = *this; result.listDepth += depth; return result; } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/any.c++0000644000175000017500000001731014712011043017706 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "any.h" #include #if !CAPNP_LITE #include "capability.h" #endif // !CAPNP_LITE namespace capnp { #if !CAPNP_LITE kj::Own PipelineHook::getPipelinedCap(kj::Array&& ops) { return getPipelinedCap(ops.asPtr()); } kj::Own AnyPointer::Reader::getPipelinedCap( kj::ArrayPtr ops) const { _::PointerReader pointer = reader; for (auto& op: ops) { switch (op.type) { case PipelineOp::Type::NOOP: break; case PipelineOp::Type::GET_POINTER_FIELD: pointer = pointer.getStruct(nullptr).getPointerField(bounded(op.pointerIndex) * POINTERS); break; } } return pointer.getCapability(); } AnyPointer::Pipeline AnyPointer::Pipeline::noop() { auto newOps = kj::heapArray(ops.size()); for (auto i: kj::indices(ops)) { newOps[i] = ops[i]; } return Pipeline(hook->addRef(), kj::mv(newOps)); } AnyPointer::Pipeline AnyPointer::Pipeline::getPointerField(uint16_t pointerIndex) { auto newOps = kj::heapArray(ops.size() + 1); for (auto i: kj::indices(ops)) { newOps[i] = ops[i]; } auto& newOp = newOps[ops.size()]; newOp.type = PipelineOp::GET_POINTER_FIELD; newOp.pointerIndex = pointerIndex; return Pipeline(hook->addRef(), kj::mv(newOps)); } kj::Own AnyPointer::Pipeline::asCap() { return hook->getPipelinedCap(ops); } #endif // !CAPNP_LITE Equality AnyStruct::Reader::equals(AnyStruct::Reader right) const { auto dataL = getDataSection(); size_t dataSizeL = dataL.size(); while(dataSizeL > 0 && dataL[dataSizeL - 1] == 0) { -- dataSizeL; } auto dataR = right.getDataSection(); size_t dataSizeR = dataR.size(); while(dataSizeR > 0 && dataR[dataSizeR - 1] == 0) { -- dataSizeR; } if(dataSizeL != dataSizeR) { return Equality::NOT_EQUAL; } if(0 != memcmp(dataL.begin(), dataR.begin(), dataSizeL)) { return Equality::NOT_EQUAL; } auto ptrsL = getPointerSection(); size_t ptrsSizeL = ptrsL.size(); while (ptrsSizeL > 0 && ptrsL[ptrsSizeL - 1].isNull()) { -- ptrsSizeL; } auto ptrsR = right.getPointerSection(); size_t ptrsSizeR = ptrsR.size(); while (ptrsSizeR > 0 && ptrsR[ptrsSizeR - 1].isNull()) { -- ptrsSizeR; } if(ptrsSizeL != ptrsSizeR) { return Equality::NOT_EQUAL; } size_t i = 0; auto eqResult = Equality::EQUAL; for (; i < ptrsSizeL; i++) { auto l = ptrsL[i]; auto r = ptrsR[i]; switch(l.equals(r)) { case Equality::EQUAL: break; case Equality::NOT_EQUAL: return Equality::NOT_EQUAL; case Equality::UNKNOWN_CONTAINS_CAPS: eqResult = Equality::UNKNOWN_CONTAINS_CAPS; break; default: KJ_UNREACHABLE; } } return eqResult; } kj::StringPtr KJ_STRINGIFY(Equality res) { switch(res) { case Equality::NOT_EQUAL: return "NOT_EQUAL"; case Equality::EQUAL: return "EQUAL"; case Equality::UNKNOWN_CONTAINS_CAPS: return "UNKNOWN_CONTAINS_CAPS"; } KJ_UNREACHABLE; } Equality AnyList::Reader::equals(AnyList::Reader right) const { if(size() != right.size()) { return Equality::NOT_EQUAL; } if (getElementSize() != right.getElementSize()) { return Equality::NOT_EQUAL; } auto eqResult = Equality::EQUAL; switch(getElementSize()) { case ElementSize::VOID: case ElementSize::BIT: case ElementSize::BYTE: case ElementSize::TWO_BYTES: case ElementSize::FOUR_BYTES: case ElementSize::EIGHT_BYTES: { size_t cmpSize = getRawBytes().size(); if (getElementSize() == ElementSize::BIT && size() % 8 != 0) { // The list does not end on a byte boundary. We need special handling for the final // byte because we only care about the bits that are actually elements of the list. uint8_t mask = (1 << (size() % 8)) - 1; // lowest size() bits set if ((getRawBytes()[cmpSize - 1] & mask) != (right.getRawBytes()[cmpSize - 1] & mask)) { return Equality::NOT_EQUAL; } cmpSize -= 1; } if (memcmp(getRawBytes().begin(), right.getRawBytes().begin(), cmpSize) == 0) { return Equality::EQUAL; } else { return Equality::NOT_EQUAL; } } case ElementSize::POINTER: case ElementSize::INLINE_COMPOSITE: { auto llist = as>(); auto rlist = right.as>(); for(size_t i = 0; i < size(); i++) { switch(llist[i].equals(rlist[i])) { case Equality::EQUAL: break; case Equality::NOT_EQUAL: return Equality::NOT_EQUAL; case Equality::UNKNOWN_CONTAINS_CAPS: eqResult = Equality::UNKNOWN_CONTAINS_CAPS; break; default: KJ_UNREACHABLE; } } return eqResult; } } KJ_UNREACHABLE; } Equality AnyPointer::Reader::equals(AnyPointer::Reader right) const { if(getPointerType() != right.getPointerType()) { return Equality::NOT_EQUAL; } switch(getPointerType()) { case PointerType::NULL_: return Equality::EQUAL; case PointerType::STRUCT: return getAs().equals(right.getAs()); case PointerType::LIST: return getAs().equals(right.getAs()); case PointerType::CAPABILITY: return Equality::UNKNOWN_CONTAINS_CAPS; } // There aren't currently any other types of pointers KJ_UNREACHABLE; } bool AnyPointer::Reader::operator==(AnyPointer::Reader right) const { switch(equals(right)) { case Equality::EQUAL: return true; case Equality::NOT_EQUAL: return false; case Equality::UNKNOWN_CONTAINS_CAPS: KJ_FAIL_REQUIRE( "operator== cannot determine equality of capabilities; use equals() instead if you need to handle this case"); } KJ_UNREACHABLE; } bool AnyStruct::Reader::operator==(AnyStruct::Reader right) const { switch(equals(right)) { case Equality::EQUAL: return true; case Equality::NOT_EQUAL: return false; case Equality::UNKNOWN_CONTAINS_CAPS: KJ_FAIL_REQUIRE( "operator== cannot determine equality of capabilities; use equals() instead if you need to handle this case"); } KJ_UNREACHABLE; } bool AnyList::Reader::operator==(AnyList::Reader right) const { switch(equals(right)) { case Equality::EQUAL: return true; case Equality::NOT_EQUAL: return false; case Equality::UNKNOWN_CONTAINS_CAPS: KJ_FAIL_REQUIRE( "operator== cannot determine equality of capabilities; use equals() instead if you need to handle this case"); } KJ_UNREACHABLE; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/raw-schema.h0000644000175000017500000002135114527152321021036 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "common.h" // for uint and friends #if _MSC_VER && !defined(__clang__) #include #endif CAPNP_BEGIN_HEADER namespace capnp { namespace _ { // private struct RawSchema; struct RawBrandedSchema { // Represents a combination of a schema and bindings for its generic parameters. // // Note that while we generate one `RawSchema` per type, we generate a `RawBrandedSchema` for // every _instance_ of a generic type -- or, at least, every instance that is actually used. For // generated-code types, we use template magic to initialize these. const RawSchema* generic; // Generic type which we're branding. struct Binding { uint8_t which; // Numeric value of one of schema::Type::Which. bool isImplicitParameter; // For AnyPointer, true if it's an implicit method parameter. uint16_t listDepth; // Number of times to wrap the base type in List(). uint16_t paramIndex; // For AnyPointer. If it's a type parameter (scopeId is non-zero) or it's an implicit parameter // (isImplicitParameter is true), then this is the parameter index. Otherwise this is a numeric // value of one of schema::Type::AnyPointer::Unconstrained::Which. union { const RawBrandedSchema* schema; // for struct, enum, interface uint64_t scopeId; // for AnyPointer, if it's a type parameter }; Binding() = default; inline constexpr Binding(uint8_t which, uint16_t listDepth, const RawBrandedSchema* schema) : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(0), schema(schema) {} inline constexpr Binding(uint8_t which, uint16_t listDepth, uint64_t scopeId, uint16_t paramIndex) : which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(paramIndex), scopeId(scopeId) {} inline constexpr Binding(uint8_t which, uint16_t listDepth, uint16_t implicitParamIndex) : which(which), isImplicitParameter(true), listDepth(listDepth), paramIndex(implicitParamIndex), scopeId(0) {} }; struct Scope { uint64_t typeId; // Type ID whose parameters are being bound. const Binding* bindings; uint bindingCount; // Bindings for those parameters. bool isUnbound; // This scope is unbound, in the sense of SchemaLoader::getUnbound(). }; const Scope* scopes; // Array of enclosing scopes for which generic variables have been bound, sorted by type ID. struct Dependency { uint location; const RawBrandedSchema* schema; }; const Dependency* dependencies; // Map of branded schemas for dependencies of this type, given our brand. Only dependencies that // are branded are included in this map; if a dependency is missing, use its `defaultBrand`. uint32_t scopeCount; uint32_t dependencyCount; enum class DepKind { // Component of a Dependency::location. Specifies what sort of dependency this is. INVALID, // Mostly defined to ensure that zero is not a valid location. FIELD, // Binding needed for a field's type. The index is the field index (NOT ordinal!). METHOD_PARAMS, // Bindings needed for a method's params type. The index is the method number. METHOD_RESULTS, // Bindings needed for a method's results type. The index is the method ordinal. SUPERCLASS, // Bindings needed for a superclass type. The index is the superclass's index in the // "extends" list. CONST_TYPE // Bindings needed for the type of a constant. The index is zero. }; static inline uint makeDepLocation(DepKind kind, uint index) { // Make a number representing the location of a particular dependency within its parent // schema. return (static_cast(kind) << 24) | index; } class Initializer { public: virtual void init(const RawBrandedSchema* generic) const = 0; }; const Initializer* lazyInitializer; // Lazy initializer, invoked by ensureInitialized(). inline void ensureInitialized() const { // Lazy initialization support. Invoke to ensure that initialization has taken place. This // is required in particular when traversing the dependency list. RawSchemas for compiled-in // types are always initialized; only dynamically-loaded schemas may be lazy. #if __GNUC__ || defined(__clang__) const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE); #elif _MSC_VER const Initializer* i = *static_cast(&lazyInitializer); std::atomic_thread_fence(std::memory_order_acquire); #else #error "Platform not supported" #endif if (i != nullptr) i->init(this); } inline bool isUnbound() const; // Checks if this schema is the result of calling SchemaLoader::getUnbound(), in which case // binding lookups need to be handled specially. }; struct RawSchema { // The generated code defines a constant RawSchema for every compiled declaration. // // This is an internal structure which could change in the future. uint64_t id; const word* encodedNode; // Encoded SchemaNode, readable via readMessageUnchecked(encodedNode). uint32_t encodedSize; // Size of encodedNode, in words. const RawSchema* const* dependencies; // Pointers to other types on which this one depends, sorted by ID. The schemas in this table // may be uninitialized -- you must call ensureInitialized() on the one you wish to use before // using it. // // TODO(someday): Make this a hashtable. const uint16_t* membersByName; // Indexes of members sorted by name. Used to implement name lookup. // TODO(someday): Make this a hashtable. uint32_t dependencyCount; uint32_t memberCount; // Sizes of above tables. const uint16_t* membersByDiscriminant; // List of all member indexes ordered by discriminant value. Those which don't have a // discriminant value are listed at the end, in order by ordinal. const RawSchema* canCastTo; // Points to the RawSchema of a compiled-in type to which it is safe to cast any DynamicValue // with this schema. This is null for all compiled-in types; it is only set by SchemaLoader on // dynamically-loaded types. class Initializer { public: virtual void init(const RawSchema* schema) const = 0; }; const Initializer* lazyInitializer; // Lazy initializer, invoked by ensureInitialized(). inline void ensureInitialized() const { // Lazy initialization support. Invoke to ensure that initialization has taken place. This // is required in particular when traversing the dependency list. RawSchemas for compiled-in // types are always initialized; only dynamically-loaded schemas may be lazy. #if __GNUC__ || defined(__clang__) const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE); #elif _MSC_VER const Initializer* i = *static_cast(&lazyInitializer); std::atomic_thread_fence(std::memory_order_acquire); #else #error "Platform not supported" #endif if (i != nullptr) i->init(this); } RawBrandedSchema defaultBrand; // Specifies the brand to use for this schema if no generic parameters have been bound to // anything. Generally, in the default brand, all generic parameters are treated as if they were // bound to `AnyPointer`. bool mayContainCapabilities = true; // See StructSchema::mayContainCapabilities. }; inline bool RawBrandedSchema::isUnbound() const { // The unbound schema is the only one that has no scopes but is not the default schema. return scopeCount == 0 && this != &generic->defaultBrand; } } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/blob.c++0000644000175000017500000000240614527152321020046 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "blob.h" namespace capnp { char Text::Builder::nulstr[1] = ""; } // namespace capnp capnproto-c++-1.1.0/src/capnp/c++.capnp.c++0000644000175000017500000001011214527152321020571 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: c++.capnp #include "c++.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<21> b_b9c6f99ebf805f2c = { { 0, 0, 0, 0, 5, 0, 6, 0, 44, 95, 128, 191, 158, 249, 198, 185, 16, 0, 0, 0, 5, 0, 1, 0, 129, 78, 48, 184, 123, 125, 248, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 210, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 43, 43, 46, 99, 97, 112, 110, 112, 58, 110, 97, 109, 101, 115, 112, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b9c6f99ebf805f2c = b_b9c6f99ebf805f2c.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = { 0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 21, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_b9c6f99ebf805f2c, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<20> b_f264a779fef191ce = { { 0, 0, 0, 0, 5, 0, 6, 0, 206, 145, 241, 254, 121, 167, 100, 242, 16, 0, 0, 0, 5, 0, 252, 7, 129, 78, 48, 184, 123, 125, 248, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 170, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 43, 43, 46, 99, 97, 112, 110, 112, 58, 110, 97, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f264a779fef191ce = b_f264a779fef191ce.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_f264a779fef191ce = { 0xf264a779fef191ce, b_f264a779fef191ce.words, 20, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_f264a779fef191ce, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<22> b_ac7096ff8cfc9dce = { { 0, 0, 0, 0, 5, 0, 6, 0, 206, 157, 252, 140, 255, 150, 112, 172, 16, 0, 0, 0, 5, 0, 1, 3, 129, 78, 48, 184, 123, 125, 248, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 43, 43, 46, 99, 97, 112, 110, 112, 58, 97, 108, 108, 111, 119, 67, 97, 110, 99, 101, 108, 108, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ac7096ff8cfc9dce = b_ac7096ff8cfc9dce.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_ac7096ff8cfc9dce = { 0xac7096ff8cfc9dce, b_ac7096ff8cfc9dce.words, 22, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_ac7096ff8cfc9dce, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema-loader.c++0000644000175000017500000024404014712011043021625 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_PRIVATE #include "schema-loader.h" #include "message.h" #include "arena.h" #include #include #include #include #include #include #include #if _MSC_VER && !defined(__clang__) #include #endif namespace capnp { namespace { struct SchemaBindingsPair { const _::RawSchema* schema; const _::RawBrandedSchema::Scope* scopeBindings; inline bool operator==(const SchemaBindingsPair& other) const { return schema == other.schema && scopeBindings == other.scopeBindings; } inline uint hashCode() const { return kj::hashCode(schema, scopeBindings); } }; } // namespace bool hasDiscriminantValue(const schema::Field::Reader& reader) { return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; } class SchemaLoader::InitializerImpl: public _::RawSchema::Initializer { public: inline explicit InitializerImpl(const SchemaLoader& loader): loader(loader), callback(nullptr) {} inline InitializerImpl(const SchemaLoader& loader, const LazyLoadCallback& callback) : loader(loader), callback(callback) {} inline kj::Maybe getCallback() const { return callback; } void init(const _::RawSchema* schema) const override; inline bool operator==(decltype(nullptr)) const { return callback == nullptr; } private: const SchemaLoader& loader; kj::Maybe callback; }; class SchemaLoader::BrandedInitializerImpl: public _::RawBrandedSchema::Initializer { public: inline explicit BrandedInitializerImpl(const SchemaLoader& loader): loader(loader) {} void init(const _::RawBrandedSchema* schema) const override; private: const SchemaLoader& loader; }; class SchemaLoader::Impl { public: inline explicit Impl(const SchemaLoader& loader) : initializer(loader), brandedInitializer(loader) {} inline Impl(const SchemaLoader& loader, const LazyLoadCallback& callback) : initializer(loader, callback), brandedInitializer(loader) {} _::RawSchema* load(const schema::Node::Reader& reader, bool isPlaceholder); _::RawSchema* loadNative(const _::RawSchema* nativeSchema); _::RawSchema* loadEmpty(uint64_t id, kj::StringPtr name, schema::Node::Which kind, bool isPlaceholder); // Create a dummy empty schema of the given kind for the given id and load it. const _::RawBrandedSchema* makeBranded( const _::RawSchema* schema, schema::Brand::Reader proto, kj::Maybe> clientBrand); struct TryGetResult { _::RawSchema* schema; kj::Maybe callback; }; TryGetResult tryGet(uint64_t typeId) const; const _::RawBrandedSchema* getUnbound(const _::RawSchema* schema); kj::Array getAllLoaded() const; void computeOptimizationHints(); void requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount); // Require any struct nodes loaded with this ID -- in the past and in the future -- to have at // least the given sizes. Struct nodes that don't comply will simply be rewritten to comply. // This is used to ensure that parents of group nodes have at least the size of the group node, // so that allocating a struct that contains a group then getting the group node and setting // its fields can't possibly write outside of the allocated space. kj::Arena arena; private: kj::HashSet> dedupTable; // Records raw segments of memory in the arena against which we my want to de-dupe later // additions. Specifically, RawBrandedSchema binding tables are de-duped. kj::HashMap schemas; kj::HashMap brands; kj::HashMap unboundBrands; struct RequiredSize { uint16_t dataWordCount; uint16_t pointerCount; }; kj::HashMap structSizeRequirements; InitializerImpl initializer; BrandedInitializerImpl brandedInitializer; kj::ArrayPtr makeUncheckedNode(schema::Node::Reader node); // Construct a copy of the given schema node, allocated as a single-segment ("unchecked") node // within the loader's arena. kj::ArrayPtr makeUncheckedNodeEnforcingSizeRequirements(schema::Node::Reader node); // Like makeUncheckedNode() but if structSizeRequirements has a requirement for this node which // is larger than the node claims to be, the size will be edited to comply. This should be rare. // If the incoming node is not a struct, any struct size requirements will be ignored, but if // such requirements exist, this indicates an inconsistency that could cause exceptions later on // (but at least can't cause memory corruption). kj::ArrayPtr rewriteStructNodeWithSizes( schema::Node::Reader node, uint dataWordCount, uint pointerCount); // Make a copy of the given node (which must be a struct node) and set its sizes to be the max // of what it said already and the given sizes. // If the encoded node does not meet the given struct size requirements, make a new copy that // does. void applyStructSizeRequirement(_::RawSchema* raw, uint dataWordCount, uint pointerCount); const _::RawBrandedSchema* makeBranded(const _::RawSchema* schema, kj::ArrayPtr scopes); kj::ArrayPtr makeBrandedDependencies( const _::RawSchema* schema, kj::Maybe> bindings); void makeDep(_::RawBrandedSchema::Binding& result, schema::Type::Reader type, kj::StringPtr scopeName, kj::Maybe> brandBindings); void makeDep(_::RawBrandedSchema::Binding& result, uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, schema::Brand::Reader brand, kj::StringPtr scopeName, kj::Maybe> brandBindings); // Looks up the schema and brand for a dependency, or creates lazily-evaluated placeholders if // they don't already exist, and fills in `result`. `scopeName` is a human-readable name of the // place where the type appeared. // // Note that we don't simply return a Binding because we need to be careful about initialization // to ensure that our byte-based de-duplification works. If we constructed a Binding on the stack // and returned it, padding bytes in that Binding could go uninitialized, causing it to appear // unique when it's not. It is expected that `result` has been zero'd via memset() before these // methods are called. const _::RawBrandedSchema* makeDepSchema( schema::Type::Reader type, kj::StringPtr scopeName, kj::Maybe> brandBindings); const _::RawBrandedSchema* makeDepSchema( uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, schema::Brand::Reader brand, kj::StringPtr scopeName, kj::Maybe> brandBindings); // Invoke makeDep() then return the result's schema, or nullptr if it's a primitive type. template kj::ArrayPtr copyDeduped(kj::ArrayPtr values); template kj::ArrayPtr copyDeduped(kj::ArrayPtr values); // Copy the given array into the arena and return the copy -- unless an identical array // was copied previously, in which case the existing copy is returned. friend class SchemaLoader::BrandedInitializerImpl; }; // ======================================================================================= inline static void verifyVoid(Void value) {} // Calls to this will break if the parameter type changes to non-void. We use this to detect // when the code needs updating. class SchemaLoader::Validator { public: Validator(SchemaLoader::Impl& loader): loader(loader) {} bool validate(const schema::Node::Reader& node) { isValid = true; nodeName = node.getDisplayName(); dependencies.clear(); KJ_CONTEXT("validating schema node", nodeName, (uint)node.which()); if (node.getParameters().size() > 0) { KJ_REQUIRE(node.getIsGeneric(), "if parameter list is non-empty, isGeneric must be true") { isValid = false; return false; } } switch (node.which()) { case schema::Node::FILE: verifyVoid(node.getFile()); break; case schema::Node::STRUCT: validate(node.getStruct(), node.getScopeId()); break; case schema::Node::ENUM: validate(node.getEnum()); break; case schema::Node::INTERFACE: validate(node.getInterface()); break; case schema::Node::CONST: validate(node.getConst()); break; case schema::Node::ANNOTATION: validate(node.getAnnotation()); break; } // We accept and pass through node types we don't recognize. return isValid; } const _::RawSchema** makeDependencyArray(uint32_t* count) { *count = dependencies.size(); kj::ArrayPtr result = loader.arena.allocateArray(*count); uint pos = 0; for (auto& dep: dependencies) { result[pos++] = dep.value; } KJ_DASSERT(pos == *count); return result.begin(); } const uint16_t* makeMemberInfoArray(uint32_t* count) { *count = members.size(); kj::ArrayPtr result = loader.arena.allocateArray(*count); uint pos = 0; for (auto& member: members) { result[pos++] = member.value; } KJ_DASSERT(pos == *count); return result.begin(); } const uint16_t* makeMembersByDiscriminantArray() { return membersByDiscriminant.begin(); } private: SchemaLoader::Impl& loader; Text::Reader nodeName; bool isValid; // Maps type IDs -> compiled schemas for each dependency. // Order is important because makeDependencyArray() compiles a sorted array. kj::TreeMap dependencies; // Maps name -> index for each member. // Order is important because makeMemberInfoArray() compiles a sorted array. kj::TreeMap members; kj::ArrayPtr membersByDiscriminant; #define VALIDATE_SCHEMA(condition, ...) \ KJ_REQUIRE(condition, ##__VA_ARGS__) { isValid = false; return; } #define FAIL_VALIDATE_SCHEMA(...) \ KJ_FAIL_REQUIRE(__VA_ARGS__) { isValid = false; return; } void validateMemberName(kj::StringPtr name, uint index) { members.upsert(name, index, [&](auto&, auto&&) { FAIL_VALIDATE_SCHEMA("duplicate name", name); }); } void validate(const schema::Node::Struct::Reader& structNode, uint64_t scopeId) { uint dataSizeInBits = structNode.getDataWordCount() * 64; uint pointerCount = structNode.getPointerCount(); auto fields = structNode.getFields(); KJ_STACK_ARRAY(bool, sawCodeOrder, fields.size(), 32, 256); memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); KJ_STACK_ARRAY(bool, sawDiscriminantValue, structNode.getDiscriminantCount(), 32, 256); memset(sawDiscriminantValue.begin(), 0, sawDiscriminantValue.size() * sizeof(sawDiscriminantValue[0])); if (structNode.getDiscriminantCount() > 0) { VALIDATE_SCHEMA(structNode.getDiscriminantCount() != 1, "union must have at least two members"); VALIDATE_SCHEMA(structNode.getDiscriminantCount() <= fields.size(), "struct can't have more union fields than total fields"); VALIDATE_SCHEMA((structNode.getDiscriminantOffset() + 1) * 16 <= dataSizeInBits, "union discriminant is out-of-bounds"); } membersByDiscriminant = loader.arena.allocateArray(fields.size()); uint discriminantPos = 0; uint nonDiscriminantPos = structNode.getDiscriminantCount(); uint index = 0; uint nextOrdinal = 0; for (auto field: fields) { KJ_CONTEXT("validating struct field", field.getName()); validateMemberName(field.getName(), index); VALIDATE_SCHEMA(field.getCodeOrder() < sawCodeOrder.size() && !sawCodeOrder[field.getCodeOrder()], "invalid codeOrder"); sawCodeOrder[field.getCodeOrder()] = true; auto ordinal = field.getOrdinal(); if (ordinal.isExplicit()) { VALIDATE_SCHEMA(ordinal.getExplicit() >= nextOrdinal, "fields were not ordered by ordinal"); nextOrdinal = ordinal.getExplicit() + 1; } if (hasDiscriminantValue(field)) { VALIDATE_SCHEMA(field.getDiscriminantValue() < sawDiscriminantValue.size() && !sawDiscriminantValue[field.getDiscriminantValue()], "invalid discriminantValue"); sawDiscriminantValue[field.getDiscriminantValue()] = true; membersByDiscriminant[discriminantPos++] = index; } else { VALIDATE_SCHEMA(nonDiscriminantPos <= fields.size(), "discriminantCount did not match fields"); membersByDiscriminant[nonDiscriminantPos++] = index; } switch (field.which()) { case schema::Field::SLOT: { auto slot = field.getSlot(); uint fieldBits = 0; bool fieldIsPointer = false; validate(slot.getType(), slot.getDefaultValue(), &fieldBits, &fieldIsPointer); VALIDATE_SCHEMA(fieldBits * (slot.getOffset() + 1) <= dataSizeInBits && fieldIsPointer * (slot.getOffset() + 1) <= pointerCount, "field offset out-of-bounds", slot.getOffset(), dataSizeInBits, pointerCount); break; } case schema::Field::GROUP: // Require that the group is a struct node. validateTypeId(field.getGroup().getTypeId(), schema::Node::STRUCT); break; } ++index; } // If the above code is correct, these should pass. KJ_ASSERT(discriminantPos == structNode.getDiscriminantCount()); KJ_ASSERT(nonDiscriminantPos == fields.size()); if (structNode.getIsGroup()) { VALIDATE_SCHEMA(scopeId != 0, "group node missing scopeId"); // Require that the group's scope has at least the same size as the group, so that anyone // constructing an instance of the outer scope can safely read/write the group. loader.requireStructSize(scopeId, structNode.getDataWordCount(), structNode.getPointerCount()); // Require that the parent type is a struct. validateTypeId(scopeId, schema::Node::STRUCT); } } void validate(const schema::Node::Enum::Reader& enumNode) { auto enumerants = enumNode.getEnumerants(); KJ_STACK_ARRAY(bool, sawCodeOrder, enumerants.size(), 32, 256); memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); uint index = 0; for (auto enumerant: enumerants) { validateMemberName(enumerant.getName(), index++); VALIDATE_SCHEMA(enumerant.getCodeOrder() < enumerants.size() && !sawCodeOrder[enumerant.getCodeOrder()], "invalid codeOrder", enumerant.getName()); sawCodeOrder[enumerant.getCodeOrder()] = true; } } void validate(const schema::Node::Interface::Reader& interfaceNode) { for (auto extend: interfaceNode.getSuperclasses()) { validateTypeId(extend.getId(), schema::Node::INTERFACE); validate(extend.getBrand()); } auto methods = interfaceNode.getMethods(); KJ_STACK_ARRAY(bool, sawCodeOrder, methods.size(), 32, 256); memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); uint index = 0; for (auto method: methods) { KJ_CONTEXT("validating method", method.getName()); validateMemberName(method.getName(), index++); VALIDATE_SCHEMA(method.getCodeOrder() < methods.size() && !sawCodeOrder[method.getCodeOrder()], "invalid codeOrder"); sawCodeOrder[method.getCodeOrder()] = true; validateTypeId(method.getParamStructType(), schema::Node::STRUCT); validate(method.getParamBrand()); validateTypeId(method.getResultStructType(), schema::Node::STRUCT); validate(method.getResultBrand()); } } void validate(const schema::Node::Const::Reader& constNode) { uint dummy1; bool dummy2; validate(constNode.getType(), constNode.getValue(), &dummy1, &dummy2); } void validate(const schema::Node::Annotation::Reader& annotationNode) { validate(annotationNode.getType()); } void validate(const schema::Type::Reader& type, const schema::Value::Reader& value, uint* dataSizeInBits, bool* isPointer) { validate(type); schema::Value::Which expectedValueType = schema::Value::VOID; bool hadCase = false; switch (type.which()) { #define HANDLE_TYPE(name, bits, ptr) \ case schema::Type::name: \ expectedValueType = schema::Value::name; \ *dataSizeInBits = bits; *isPointer = ptr; \ hadCase = true; \ break; HANDLE_TYPE(VOID, 0, false) HANDLE_TYPE(BOOL, 1, false) HANDLE_TYPE(INT8, 8, false) HANDLE_TYPE(INT16, 16, false) HANDLE_TYPE(INT32, 32, false) HANDLE_TYPE(INT64, 64, false) HANDLE_TYPE(UINT8, 8, false) HANDLE_TYPE(UINT16, 16, false) HANDLE_TYPE(UINT32, 32, false) HANDLE_TYPE(UINT64, 64, false) HANDLE_TYPE(FLOAT32, 32, false) HANDLE_TYPE(FLOAT64, 64, false) HANDLE_TYPE(TEXT, 0, true) HANDLE_TYPE(DATA, 0, true) HANDLE_TYPE(LIST, 0, true) HANDLE_TYPE(ENUM, 16, false) HANDLE_TYPE(STRUCT, 0, true) HANDLE_TYPE(INTERFACE, 0, true) HANDLE_TYPE(ANY_POINTER, 0, true) #undef HANDLE_TYPE } if (hadCase) { VALIDATE_SCHEMA(value.which() == expectedValueType, "Value did not match type.", (uint)value.which(), (uint)expectedValueType); } } void validate(const schema::Type::Reader& type) { switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ANY_POINTER: break; case schema::Type::STRUCT: { auto structType = type.getStruct(); validateTypeId(structType.getTypeId(), schema::Node::STRUCT); validate(structType.getBrand()); break; } case schema::Type::ENUM: { auto enumType = type.getEnum(); validateTypeId(enumType.getTypeId(), schema::Node::ENUM); validate(enumType.getBrand()); break; } case schema::Type::INTERFACE: { auto interfaceType = type.getInterface(); validateTypeId(interfaceType.getTypeId(), schema::Node::INTERFACE); validate(interfaceType.getBrand()); break; } case schema::Type::LIST: validate(type.getList().getElementType()); break; } // We intentionally allow unknown types. } void validate(const schema::Brand::Reader& brand) { for (auto scope: brand.getScopes()) { switch (scope.which()) { case schema::Brand::Scope::BIND: for (auto binding: scope.getBind()) { switch (binding.which()) { case schema::Brand::Binding::UNBOUND: break; case schema::Brand::Binding::TYPE: { auto type = binding.getType(); validate(type); bool isPointer = true; switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: isPointer = false; break; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ANY_POINTER: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::LIST: isPointer = true; break; } VALIDATE_SCHEMA(isPointer, "generic type parameter must be a pointer type", type); break; } } } break; case schema::Brand::Scope::INHERIT: break; } } } void validateTypeId(uint64_t id, schema::Node::Which expectedKind) { _::RawSchema* existing = loader.tryGet(id).schema; if (existing != nullptr) { auto node = readMessageUnchecked(existing->encodedNode); VALIDATE_SCHEMA(node.which() == expectedKind, "expected a different kind of node for this ID", id, (uint)expectedKind, (uint)node.which(), node.getDisplayName()); dependencies.upsert(id, existing, [](auto&,auto&&) { /* ignore dupe */ }); return; } dependencies.upsert(id, loader.loadEmpty( id, kj::str("(unknown type used by ", nodeName , ")"), expectedKind, true), [](auto&,auto&&) { /* ignore dupe */ }); } #undef VALIDATE_SCHEMA #undef FAIL_VALIDATE_SCHEMA }; // ======================================================================================= class SchemaLoader::CompatibilityChecker { public: CompatibilityChecker(SchemaLoader::Impl& loader): loader(loader) {} bool shouldReplace(const schema::Node::Reader& existingNode, const schema::Node::Reader& replacement, bool preferReplacementIfEquivalent) { this->existingNode = existingNode; this->replacementNode = replacement; KJ_CONTEXT("checking compatibility with previously-loaded node of the same id", existingNode.getDisplayName()); KJ_DREQUIRE(existingNode.getId() == replacement.getId()); nodeName = existingNode.getDisplayName(); compatibility = EQUIVALENT; checkCompatibility(existingNode, replacement); // Prefer the newer schema. return preferReplacementIfEquivalent ? compatibility != OLDER : compatibility == NEWER; } private: SchemaLoader::Impl& loader; Text::Reader nodeName; schema::Node::Reader existingNode; schema::Node::Reader replacementNode; enum Compatibility { EQUIVALENT, OLDER, NEWER, INCOMPATIBLE }; Compatibility compatibility; #define VALIDATE_SCHEMA(condition, ...) \ KJ_REQUIRE(condition, ##__VA_ARGS__) { compatibility = INCOMPATIBLE; return; } #define FAIL_VALIDATE_SCHEMA(...) \ KJ_FAIL_REQUIRE(__VA_ARGS__) { compatibility = INCOMPATIBLE; return; } void replacementIsNewer() { switch (compatibility) { case EQUIVALENT: compatibility = NEWER; break; case OLDER: FAIL_VALIDATE_SCHEMA("Schema node contains some changes that are upgrades and some " "that are downgrades. All changes must be in the same direction for compatibility."); break; case NEWER: break; case INCOMPATIBLE: break; } } void replacementIsOlder() { switch (compatibility) { case EQUIVALENT: compatibility = OLDER; break; case OLDER: break; case NEWER: FAIL_VALIDATE_SCHEMA("Schema node contains some changes that are upgrades and some " "that are downgrades. All changes must be in the same direction for compatibility."); break; case INCOMPATIBLE: break; } } void checkCompatibility(const schema::Node::Reader& node, const schema::Node::Reader& replacement) { // Returns whether `replacement` is equivalent, older than, newer than, or incompatible with // `node`. If exceptions are enabled, this will throw an exception on INCOMPATIBLE. VALIDATE_SCHEMA(node.which() == replacement.which(), "kind of declaration changed"); // No need to check compatibility of most of the non-body parts of the node: // - Arbitrary renaming and moving between scopes is allowed. // - Annotations are ignored for compatibility purposes. if (replacement.getParameters().size() > node.getParameters().size()) { replacementIsNewer(); } else if (replacement.getParameters().size() < node.getParameters().size()) { replacementIsOlder(); } switch (node.which()) { case schema::Node::FILE: verifyVoid(node.getFile()); break; case schema::Node::STRUCT: checkCompatibility(node.getStruct(), replacement.getStruct(), node.getScopeId(), replacement.getScopeId()); break; case schema::Node::ENUM: checkCompatibility(node.getEnum(), replacement.getEnum()); break; case schema::Node::INTERFACE: checkCompatibility(node.getInterface(), replacement.getInterface()); break; case schema::Node::CONST: checkCompatibility(node.getConst(), replacement.getConst()); break; case schema::Node::ANNOTATION: checkCompatibility(node.getAnnotation(), replacement.getAnnotation()); break; } } void checkCompatibility(const schema::Node::Struct::Reader& structNode, const schema::Node::Struct::Reader& replacement, uint64_t scopeId, uint64_t replacementScopeId) { if (replacement.getDataWordCount() > structNode.getDataWordCount()) { replacementIsNewer(); } else if (replacement.getDataWordCount() < structNode.getDataWordCount()) { replacementIsOlder(); } if (replacement.getPointerCount() > structNode.getPointerCount()) { replacementIsNewer(); } else if (replacement.getPointerCount() < structNode.getPointerCount()) { replacementIsOlder(); } if (replacement.getDiscriminantCount() > structNode.getDiscriminantCount()) { replacementIsNewer(); } else if (replacement.getDiscriminantCount() < structNode.getDiscriminantCount()) { replacementIsOlder(); } if (replacement.getDiscriminantCount() > 0 && structNode.getDiscriminantCount() > 0) { VALIDATE_SCHEMA(replacement.getDiscriminantOffset() == structNode.getDiscriminantOffset(), "union discriminant position changed"); } // The shared members should occupy corresponding positions in the member lists, since the // lists are sorted by ordinal. auto fields = structNode.getFields(); auto replacementFields = replacement.getFields(); uint count = std::min(fields.size(), replacementFields.size()); if (replacementFields.size() > fields.size()) { replacementIsNewer(); } else if (replacementFields.size() < fields.size()) { replacementIsOlder(); } for (uint i = 0; i < count; i++) { checkCompatibility(fields[i], replacementFields[i]); } // For the moment, we allow "upgrading" from non-group to group, mainly so that the // placeholders we generate for group parents (which in the absence of more info, we assume to // be non-groups) can be replaced with groups. // // TODO(cleanup): The placeholder approach is really breaking down. Maybe we need to maintain // a list of expectations for nodes we haven't loaded yet. if (structNode.getIsGroup()) { if (replacement.getIsGroup()) { VALIDATE_SCHEMA(replacementScopeId == scopeId, "group node's scope changed"); } else { replacementIsOlder(); } } else { if (replacement.getIsGroup()) { replacementIsNewer(); } } } void checkCompatibility(const schema::Field::Reader& field, const schema::Field::Reader& replacement) { KJ_CONTEXT("comparing struct field", field.getName()); // A field that is initially not in a union can be upgraded to be in one, as long as it has // discriminant 0. uint discriminant = hasDiscriminantValue(field) ? field.getDiscriminantValue() : 0; uint replacementDiscriminant = hasDiscriminantValue(replacement) ? replacement.getDiscriminantValue() : 0; VALIDATE_SCHEMA(discriminant == replacementDiscriminant, "Field discriminant changed."); switch (field.which()) { case schema::Field::SLOT: { auto slot = field.getSlot(); switch (replacement.which()) { case schema::Field::SLOT: { auto replacementSlot = replacement.getSlot(); checkCompatibility(slot.getType(), replacementSlot.getType(), NO_UPGRADE_TO_STRUCT); checkDefaultCompatibility(slot.getDefaultValue(), replacementSlot.getDefaultValue()); VALIDATE_SCHEMA(slot.getOffset() == replacementSlot.getOffset(), "field position changed"); break; } case schema::Field::GROUP: checkUpgradeToStruct(slot.getType(), replacement.getGroup().getTypeId(), existingNode, field); break; } break; } case schema::Field::GROUP: switch (replacement.which()) { case schema::Field::SLOT: checkUpgradeToStruct(replacement.getSlot().getType(), field.getGroup().getTypeId(), replacementNode, replacement); break; case schema::Field::GROUP: VALIDATE_SCHEMA(field.getGroup().getTypeId() == replacement.getGroup().getTypeId(), "group id changed"); break; } break; } } void checkCompatibility(const schema::Node::Enum::Reader& enumNode, const schema::Node::Enum::Reader& replacement) { uint size = enumNode.getEnumerants().size(); uint replacementSize = replacement.getEnumerants().size(); if (replacementSize > size) { replacementIsNewer(); } else if (replacementSize < size) { replacementIsOlder(); } } void checkCompatibility(const schema::Node::Interface::Reader& interfaceNode, const schema::Node::Interface::Reader& replacement) { { // Check superclasses. kj::Vector superclasses; kj::Vector replacementSuperclasses; for (auto superclass: interfaceNode.getSuperclasses()) { superclasses.add(superclass.getId()); } for (auto superclass: replacement.getSuperclasses()) { replacementSuperclasses.add(superclass.getId()); } std::sort(superclasses.begin(), superclasses.end()); std::sort(replacementSuperclasses.begin(), replacementSuperclasses.end()); auto iter = superclasses.begin(); auto replacementIter = replacementSuperclasses.begin(); while (iter != superclasses.end() || replacementIter != replacementSuperclasses.end()) { if (iter == superclasses.end()) { replacementIsNewer(); break; } else if (replacementIter == replacementSuperclasses.end()) { replacementIsOlder(); break; } else if (*iter < *replacementIter) { replacementIsOlder(); ++iter; } else if (*iter > *replacementIter) { replacementIsNewer(); ++replacementIter; } else { ++iter; ++replacementIter; } } } auto methods = interfaceNode.getMethods(); auto replacementMethods = replacement.getMethods(); if (replacementMethods.size() > methods.size()) { replacementIsNewer(); } else if (replacementMethods.size() < methods.size()) { replacementIsOlder(); } uint count = std::min(methods.size(), replacementMethods.size()); for (uint i = 0; i < count; i++) { checkCompatibility(methods[i], replacementMethods[i]); } } void checkCompatibility(const schema::Method::Reader& method, const schema::Method::Reader& replacement) { KJ_CONTEXT("comparing method", method.getName()); // TODO(someday): Allow named parameter list to be replaced by compatible struct type. VALIDATE_SCHEMA(method.getParamStructType() == replacement.getParamStructType(), "Updated method has different parameters."); VALIDATE_SCHEMA(method.getResultStructType() == replacement.getResultStructType(), "Updated method has different results."); } void checkCompatibility(const schema::Node::Const::Reader& constNode, const schema::Node::Const::Reader& replacement) { // Who cares? These don't appear on the wire. } void checkCompatibility(const schema::Node::Annotation::Reader& annotationNode, const schema::Node::Annotation::Reader& replacement) { // Who cares? These don't appear on the wire. } enum UpgradeToStructMode { ALLOW_UPGRADE_TO_STRUCT, NO_UPGRADE_TO_STRUCT }; void checkCompatibility(const schema::Type::Reader& type, const schema::Type::Reader& replacement, UpgradeToStructMode upgradeToStructMode) { if (replacement.which() != type.which()) { // Check for allowed "upgrade" to Data or AnyPointer. if (replacement.isData() && canUpgradeToData(type)) { replacementIsNewer(); return; } else if (type.isData() && canUpgradeToData(replacement)) { replacementIsOlder(); return; } else if (replacement.isAnyPointer() && canUpgradeToAnyPointer(type)) { replacementIsNewer(); return; } else if (type.isAnyPointer() && canUpgradeToAnyPointer(replacement)) { replacementIsOlder(); return; } if (upgradeToStructMode == ALLOW_UPGRADE_TO_STRUCT) { if (type.isStruct()) { checkUpgradeToStruct(replacement, type.getStruct().getTypeId()); return; } else if (replacement.isStruct()) { checkUpgradeToStruct(type, replacement.getStruct().getTypeId()); return; } } FAIL_VALIDATE_SCHEMA("a type was changed"); } switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ANY_POINTER: return; case schema::Type::LIST: checkCompatibility(type.getList().getElementType(), replacement.getList().getElementType(), ALLOW_UPGRADE_TO_STRUCT); return; case schema::Type::ENUM: VALIDATE_SCHEMA(replacement.getEnum().getTypeId() == type.getEnum().getTypeId(), "type changed enum type"); return; case schema::Type::STRUCT: // TODO(someday): If the IDs don't match, we should compare the two structs for // compatibility. This is tricky, though, because the new type's target may not yet be // loaded. In that case we could take the old type, make a copy of it, assign the new // ID to the copy, and load() that. That forces any struct type loaded for that ID to // be compatible. However, that has another problem, which is that it could be that the // whole reason the type was replaced was to fork that type, and so an incompatibility // could be very much expected. This could be a rat hole... VALIDATE_SCHEMA(replacement.getStruct().getTypeId() == type.getStruct().getTypeId(), "type changed to incompatible struct type"); return; case schema::Type::INTERFACE: VALIDATE_SCHEMA(replacement.getInterface().getTypeId() == type.getInterface().getTypeId(), "type changed to incompatible interface type"); return; } // We assume unknown types (from newer versions of Cap'n Proto?) are equivalent. } void checkUpgradeToStruct(const schema::Type::Reader& type, uint64_t structTypeId, kj::Maybe matchSize = nullptr, kj::Maybe matchPosition = nullptr) { // We can't just look up the target struct and check it because it may not have been loaded // yet. Instead, we contrive a struct that looks like what we want and load() that, which // guarantees that any incompatibility will be caught either now or when the real version of // that struct is loaded. word scratch[32]; memset(scratch, 0, sizeof(scratch)); MallocMessageBuilder builder(scratch); auto node = builder.initRoot(); node.setId(structTypeId); node.setDisplayName(kj::str("(unknown type used in ", nodeName, ")")); auto structNode = node.initStruct(); switch (type.which()) { case schema::Type::VOID: structNode.setDataWordCount(0); structNode.setPointerCount(0); break; case schema::Type::BOOL: structNode.setDataWordCount(1); structNode.setPointerCount(0); break; case schema::Type::INT8: case schema::Type::UINT8: structNode.setDataWordCount(1); structNode.setPointerCount(0); break; case schema::Type::INT16: case schema::Type::UINT16: case schema::Type::ENUM: structNode.setDataWordCount(1); structNode.setPointerCount(0); break; case schema::Type::INT32: case schema::Type::UINT32: case schema::Type::FLOAT32: structNode.setDataWordCount(1); structNode.setPointerCount(0); break; case schema::Type::INT64: case schema::Type::UINT64: case schema::Type::FLOAT64: structNode.setDataWordCount(1); structNode.setPointerCount(0); break; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: structNode.setDataWordCount(0); structNode.setPointerCount(1); break; } KJ_IF_MAYBE(s, matchSize) { auto match = s->getStruct(); structNode.setDataWordCount(match.getDataWordCount()); structNode.setPointerCount(match.getPointerCount()); } auto field = structNode.initFields(1)[0]; field.setName("member0"); field.setCodeOrder(0); auto slot = field.initSlot(); slot.setType(type); KJ_IF_MAYBE(p, matchPosition) { if (p->getOrdinal().isExplicit()) { field.getOrdinal().setExplicit(p->getOrdinal().getExplicit()); } else { field.getOrdinal().setImplicit(); } auto matchSlot = p->getSlot(); slot.setOffset(matchSlot.getOffset()); slot.setDefaultValue(matchSlot.getDefaultValue()); } else { field.getOrdinal().setExplicit(0); slot.setOffset(0); schema::Value::Builder value = slot.initDefaultValue(); switch (type.which()) { case schema::Type::VOID: value.setVoid(); break; case schema::Type::BOOL: value.setBool(false); break; case schema::Type::INT8: value.setInt8(0); break; case schema::Type::INT16: value.setInt16(0); break; case schema::Type::INT32: value.setInt32(0); break; case schema::Type::INT64: value.setInt64(0); break; case schema::Type::UINT8: value.setUint8(0); break; case schema::Type::UINT16: value.setUint16(0); break; case schema::Type::UINT32: value.setUint32(0); break; case schema::Type::UINT64: value.setUint64(0); break; case schema::Type::FLOAT32: value.setFloat32(0); break; case schema::Type::FLOAT64: value.setFloat64(0); break; case schema::Type::ENUM: value.setEnum(0); break; case schema::Type::TEXT: value.adoptText(Orphan()); break; case schema::Type::DATA: value.adoptData(Orphan()); break; case schema::Type::LIST: value.initList(); break; case schema::Type::STRUCT: value.initStruct(); break; case schema::Type::INTERFACE: value.setInterface(); break; case schema::Type::ANY_POINTER: value.initAnyPointer(); break; } } loader.load(node, true); } bool canUpgradeToData(const schema::Type::Reader& type) { if (type.isText()) { return true; } else if (type.isList()) { switch (type.getList().getElementType().which()) { case schema::Type::INT8: case schema::Type::UINT8: return true; default: return false; } } else { return false; } } bool canUpgradeToAnyPointer(const schema::Type::Reader& type) { switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::ENUM: return false; case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::LIST: case schema::Type::STRUCT: case schema::Type::INTERFACE: case schema::Type::ANY_POINTER: return true; } // Be lenient with unknown types. return true; } void checkDefaultCompatibility(const schema::Value::Reader& value, const schema::Value::Reader& replacement) { // Note that we test default compatibility only after testing type compatibility, and default // values have already been validated as matching their types, so this should pass. KJ_ASSERT(value.which() == replacement.which()) { compatibility = INCOMPATIBLE; return; } switch (value.which()) { #define HANDLE_TYPE(discrim, name) \ case schema::Value::discrim: \ VALIDATE_SCHEMA(value.get##name() == replacement.get##name(), "default value changed"); \ break; HANDLE_TYPE(VOID, Void); HANDLE_TYPE(BOOL, Bool); HANDLE_TYPE(INT8, Int8); HANDLE_TYPE(INT16, Int16); HANDLE_TYPE(INT32, Int32); HANDLE_TYPE(INT64, Int64); HANDLE_TYPE(UINT8, Uint8); HANDLE_TYPE(UINT16, Uint16); HANDLE_TYPE(UINT32, Uint32); HANDLE_TYPE(UINT64, Uint64); HANDLE_TYPE(FLOAT32, Float32); HANDLE_TYPE(FLOAT64, Float64); HANDLE_TYPE(ENUM, Enum); #undef HANDLE_TYPE case schema::Value::TEXT: case schema::Value::DATA: case schema::Value::LIST: case schema::Value::STRUCT: case schema::Value::INTERFACE: case schema::Value::ANY_POINTER: // It's not a big deal if default values for pointers change, and it would be difficult for // us to compare these defaults here, so just let it slide. break; } } }; // ======================================================================================= _::RawSchema* SchemaLoader::Impl::load(const schema::Node::Reader& reader, bool isPlaceholder) { // Make a copy of the node which can be used unchecked. kj::ArrayPtr validated = makeUncheckedNodeEnforcingSizeRequirements(reader); // Validate the copy. Validator validator(*this); auto validatedReader = readMessageUnchecked(validated.begin()); if (!validator.validate(validatedReader)) { // Not valid. Construct an empty schema of the same type and return that. return loadEmpty(validatedReader.getId(), validatedReader.getDisplayName(), validatedReader.which(), false); } // Check if we already have a schema for this ID. _::RawSchema* schema; bool shouldReplace; bool shouldClearInitializer; KJ_IF_MAYBE(match, schemas.find(validatedReader.getId())) { // Yes, check if it is compatible and figure out which schema is newer. schema = *match; // If the existing schema is a placeholder, but we're upgrading it to a non-placeholder, we // need to clear the initializer later. shouldClearInitializer = schema->lazyInitializer != nullptr && !isPlaceholder; auto existing = readMessageUnchecked(schema->encodedNode); CompatibilityChecker checker(*this); // Prefer to replace the existing schema if the existing schema is a placeholder. Otherwise, // prefer to keep the existing schema. shouldReplace = checker.shouldReplace( existing, validatedReader, schema->lazyInitializer != nullptr); } else { // Nope, allocate a new RawSchema. schema = &arena.allocate<_::RawSchema>(); memset(&schema->defaultBrand, 0, sizeof(schema->defaultBrand)); schema->id = validatedReader.getId(); schema->canCastTo = nullptr; schema->defaultBrand.generic = schema; schema->lazyInitializer = isPlaceholder ? &initializer : nullptr; schema->defaultBrand.lazyInitializer = isPlaceholder ? &brandedInitializer : nullptr; shouldReplace = true; shouldClearInitializer = false; schemas.insert(validatedReader.getId(), schema); } if (shouldReplace) { // Initialize the RawSchema. schema->encodedNode = validated.begin(); schema->encodedSize = validated.size(); schema->dependencies = validator.makeDependencyArray(&schema->dependencyCount); schema->membersByName = validator.makeMemberInfoArray(&schema->memberCount); schema->membersByDiscriminant = validator.makeMembersByDiscriminantArray(); // Even though this schema isn't itself branded, it may have dependencies that are. So, we // need to set up the "dependencies" map under defaultBrand. auto deps = makeBrandedDependencies(schema, kj::ArrayPtr()); schema->defaultBrand.dependencies = deps.begin(); schema->defaultBrand.dependencyCount = deps.size(); } if (shouldClearInitializer) { // If this schema is not newly-allocated, it may already be in the wild, specifically in the // dependency list of other schemas. Once the initializer is null, it is live, so we must do // a release-store here. #if __GNUC__ || defined(__clang__) __atomic_store_n(&schema->lazyInitializer, nullptr, __ATOMIC_RELEASE); __atomic_store_n(&schema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); #elif _MSC_VER std::atomic_thread_fence(std::memory_order_release); *static_cast<_::RawSchema::Initializer const* volatile*>(&schema->lazyInitializer) = nullptr; *static_cast<_::RawBrandedSchema::Initializer const* volatile*>( &schema->defaultBrand.lazyInitializer) = nullptr; #else #error "Platform not supported" #endif } return schema; } _::RawSchema* SchemaLoader::Impl::loadNative(const _::RawSchema* nativeSchema) { _::RawSchema* schema; bool shouldReplace; bool shouldClearInitializer; KJ_IF_MAYBE(match, schemas.find(nativeSchema->id)) { schema = *match; if (schema->canCastTo != nullptr) { // Already loaded natively, or we're currently in the process of loading natively and there // was a dependency cycle. KJ_REQUIRE(schema->canCastTo == nativeSchema, "two different compiled-in type have the same type ID", nativeSchema->id, readMessageUnchecked(nativeSchema->encodedNode).getDisplayName(), readMessageUnchecked(schema->canCastTo->encodedNode).getDisplayName()); return schema; } else { auto existing = readMessageUnchecked(schema->encodedNode); auto native = readMessageUnchecked(nativeSchema->encodedNode); CompatibilityChecker checker(*this); shouldReplace = checker.shouldReplace(existing, native, true); shouldClearInitializer = schema->lazyInitializer != nullptr; } } else { schema = &arena.allocate<_::RawSchema>(); memset(&schema->defaultBrand, 0, sizeof(schema->defaultBrand)); schema->defaultBrand.generic = schema; schema->lazyInitializer = nullptr; schema->defaultBrand.lazyInitializer = nullptr; shouldReplace = true; shouldClearInitializer = false; // already cleared above schemas.insert(nativeSchema->id, schema); } if (shouldReplace) { // Set the schema to a copy of the native schema, but make sure not to null out lazyInitializer // yet. _::RawSchema temp = *nativeSchema; temp.lazyInitializer = schema->lazyInitializer; *schema = temp; schema->defaultBrand.generic = schema; // Indicate that casting is safe. Note that it's important to set this before recursively // loading dependencies, so that cycles don't cause infinite loops! schema->canCastTo = nativeSchema; // We need to set the dependency list to point at other loader-owned RawSchemas. kj::ArrayPtr dependencies = arena.allocateArray(schema->dependencyCount); for (uint i = 0; i < nativeSchema->dependencyCount; i++) { dependencies[i] = loadNative(nativeSchema->dependencies[i]); } schema->dependencies = dependencies.begin(); // Also need to re-do the branded dependencies. auto deps = makeBrandedDependencies(schema, kj::ArrayPtr()); schema->defaultBrand.dependencies = deps.begin(); schema->defaultBrand.dependencyCount = deps.size(); // If there is a struct size requirement, we need to make sure that it is satisfied. KJ_IF_MAYBE(sizeReq, structSizeRequirements.find(nativeSchema->id)) { applyStructSizeRequirement(schema, sizeReq->dataWordCount, sizeReq->pointerCount); } } else { // The existing schema is newer. // Indicate that casting is safe. Note that it's important to set this before recursively // loading dependencies, so that cycles don't cause infinite loops! schema->canCastTo = nativeSchema; // Make sure the dependencies are loaded and compatible. for (uint i = 0; i < nativeSchema->dependencyCount; i++) { loadNative(nativeSchema->dependencies[i]); } } if (shouldClearInitializer) { // If this schema is not newly-allocated, it may already be in the wild, specifically in the // dependency list of other schemas. Once the initializer is null, it is live, so we must do // a release-store here. #if __GNUC__ || defined(__clang__) __atomic_store_n(&schema->lazyInitializer, nullptr, __ATOMIC_RELEASE); __atomic_store_n(&schema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); #elif _MSC_VER std::atomic_thread_fence(std::memory_order_release); *static_cast<_::RawSchema::Initializer const* volatile*>(&schema->lazyInitializer) = nullptr; *static_cast<_::RawBrandedSchema::Initializer const* volatile*>( &schema->defaultBrand.lazyInitializer) = nullptr; #else #error "Platform not supported" #endif } return schema; } _::RawSchema* SchemaLoader::Impl::loadEmpty( uint64_t id, kj::StringPtr name, schema::Node::Which kind, bool isPlaceholder) { word scratch[32]; memset(scratch, 0, sizeof(scratch)); MallocMessageBuilder builder(scratch); auto node = builder.initRoot(); node.setId(id); node.setDisplayName(name); switch (kind) { case schema::Node::STRUCT: node.initStruct(); break; case schema::Node::ENUM: node.initEnum(); break; case schema::Node::INTERFACE: node.initInterface(); break; case schema::Node::FILE: case schema::Node::CONST: case schema::Node::ANNOTATION: KJ_FAIL_REQUIRE("Not a type."); break; } return load(node, isPlaceholder); } const _::RawBrandedSchema* SchemaLoader::Impl::makeBranded( const _::RawSchema* schema, schema::Brand::Reader proto, kj::Maybe> clientBrand) { kj::StringPtr scopeName = readMessageUnchecked(schema->encodedNode).getDisplayName(); auto srcScopes = proto.getScopes(); KJ_STACK_ARRAY(_::RawBrandedSchema::Scope, dstScopes, srcScopes.size(), 16, 32); memset(dstScopes.begin(), 0, dstScopes.size() * sizeof(dstScopes[0])); uint dstScopeCount = 0; for (auto srcScope: srcScopes) { switch (srcScope.which()) { case schema::Brand::Scope::BIND: { auto srcBindings = srcScope.getBind(); KJ_STACK_ARRAY(_::RawBrandedSchema::Binding, dstBindings, srcBindings.size(), 16, 32); memset(dstBindings.begin(), 0, dstBindings.size() * sizeof(dstBindings[0])); for (auto j: kj::indices(srcBindings)) { auto srcBinding = srcBindings[j]; auto& dstBinding = dstBindings[j]; memset(&dstBinding, 0, sizeof(dstBinding)); dstBinding.which = schema::Type::ANY_POINTER; switch (srcBinding.which()) { case schema::Brand::Binding::UNBOUND: break; case schema::Brand::Binding::TYPE: { makeDep(dstBinding, srcBinding.getType(), scopeName, clientBrand); break; } } } auto& dstScope = dstScopes[dstScopeCount++]; dstScope.typeId = srcScope.getScopeId(); dstScope.bindingCount = dstBindings.size(); dstScope.bindings = copyDeduped(dstBindings).begin(); break; } case schema::Brand::Scope::INHERIT: { // Inherit the whole scope from the client -- or if the client doesn't have it, at least // include an empty dstScope in the list just to show that this scope was specified as // inherited, as opposed to being unspecified (which would be treated as all AnyPointer). auto& dstScope = dstScopes[dstScopeCount++]; dstScope.typeId = srcScope.getScopeId(); KJ_IF_MAYBE(b, clientBrand) { for (auto& clientScope: *b) { if (clientScope.typeId == dstScope.typeId) { // Overwrite the whole thing. dstScope = clientScope; break; } } } else { dstScope.isUnbound = true; } break; } } } dstScopes = dstScopes.slice(0, dstScopeCount); std::sort(dstScopes.begin(), dstScopes.end(), [](const _::RawBrandedSchema::Scope& a, const _::RawBrandedSchema::Scope& b) { return a.typeId < b.typeId; }); return makeBranded(schema, copyDeduped(dstScopes)); } const _::RawBrandedSchema* SchemaLoader::Impl::makeBranded( const _::RawSchema* schema, kj::ArrayPtr bindings) { if (bindings.size() == 0) { // `defaultBrand` is the version where all type parameters are bound to `AnyPointer`. return &schema->defaultBrand; } SchemaBindingsPair key { schema, bindings.begin() }; KJ_IF_MAYBE(existing, brands.find(key)) { return *existing; } else { auto& brand = arena.allocate<_::RawBrandedSchema>(); memset(&brand, 0, sizeof(brand)); brands.insert(key, &brand); brand.generic = schema; brand.scopes = bindings.begin(); brand.scopeCount = bindings.size(); brand.lazyInitializer = &brandedInitializer; return &brand; } } kj::ArrayPtr SchemaLoader::Impl::makeBrandedDependencies( const _::RawSchema* schema, kj::Maybe> bindings) { kj::StringPtr scopeName = readMessageUnchecked(schema->encodedNode).getDisplayName(); kj::Vector<_::RawBrandedSchema::Dependency> deps; schema::Node::Reader node = readMessageUnchecked(schema->encodedNode); #define ADD_ENTRY(kind, index, make) \ if (const _::RawBrandedSchema* dep = make) { \ auto& slot = deps.add(); \ memset(&slot, 0, sizeof(slot)); \ slot.location = _::RawBrandedSchema::makeDepLocation( \ _::RawBrandedSchema::DepKind::kind, index); \ slot.schema = dep; \ } switch (node.which()) { case schema::Node::FILE: case schema::Node::ENUM: case schema::Node::ANNOTATION: break; case schema::Node::CONST: ADD_ENTRY(CONST_TYPE, 0, makeDepSchema( node.getConst().getType(), scopeName, bindings)); break; case schema::Node::STRUCT: { auto fields = node.getStruct().getFields(); for (auto i: kj::indices(fields)) { auto field = fields[i]; switch (field.which()) { case schema::Field::SLOT: ADD_ENTRY(FIELD, i, makeDepSchema( field.getSlot().getType(), scopeName, bindings)) break; case schema::Field::GROUP: { const _::RawSchema* group = loadEmpty( field.getGroup().getTypeId(), "(unknown group type)", schema::Node::STRUCT, true); KJ_IF_MAYBE(b, bindings) { ADD_ENTRY(FIELD, i, makeBranded(group, *b)); } else { ADD_ENTRY(FIELD, i, getUnbound(group)); } break; } } } break; } case schema::Node::INTERFACE: { auto interface = node.getInterface(); { auto superclasses = interface.getSuperclasses(); for (auto i: kj::indices(superclasses)) { auto superclass = superclasses[i]; ADD_ENTRY(SUPERCLASS, i, makeDepSchema( superclass.getId(), schema::Type::INTERFACE, schema::Node::INTERFACE, superclass.getBrand(), scopeName, bindings)) } } { auto methods = interface.getMethods(); for (auto i: kj::indices(methods)) { auto method = methods[i]; ADD_ENTRY(METHOD_PARAMS, i, makeDepSchema( method.getParamStructType(), schema::Type::STRUCT, schema::Node::STRUCT, method.getParamBrand(), scopeName, bindings)) ADD_ENTRY(METHOD_RESULTS, i, makeDepSchema( method.getResultStructType(), schema::Type::STRUCT, schema::Node::STRUCT, method.getResultBrand(), scopeName, bindings)) } } break; } } #undef ADD_ENTRY std::sort(deps.begin(), deps.end(), [](const _::RawBrandedSchema::Dependency& a, const _::RawBrandedSchema::Dependency& b) { return a.location < b.location; }); return copyDeduped(deps.asPtr()); } void SchemaLoader::Impl::makeDep(_::RawBrandedSchema::Binding& result, schema::Type::Reader type, kj::StringPtr scopeName, kj::Maybe> brandBindings) { switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: result.which = static_cast(type.which()); return; case schema::Type::STRUCT: { auto structType = type.getStruct(); makeDep(result, structType.getTypeId(), schema::Type::STRUCT, schema::Node::STRUCT, structType.getBrand(), scopeName, brandBindings); return; } case schema::Type::ENUM: { auto enumType = type.getEnum(); makeDep(result, enumType.getTypeId(), schema::Type::ENUM, schema::Node::ENUM, enumType.getBrand(), scopeName, brandBindings); return; } case schema::Type::INTERFACE: { auto interfaceType = type.getInterface(); makeDep(result, interfaceType.getTypeId(), schema::Type::INTERFACE, schema::Node::INTERFACE, interfaceType.getBrand(), scopeName, brandBindings); return; } case schema::Type::LIST: { makeDep(result, type.getList().getElementType(), scopeName, brandBindings); ++result.listDepth; return; } case schema::Type::ANY_POINTER: { result.which = static_cast(schema::Type::ANY_POINTER); auto anyPointer = type.getAnyPointer(); switch (anyPointer.which()) { case schema::Type::AnyPointer::UNCONSTRAINED: return; case schema::Type::AnyPointer::PARAMETER: { auto param = anyPointer.getParameter(); uint64_t id = param.getScopeId(); uint16_t index = param.getParameterIndex(); KJ_IF_MAYBE(b, brandBindings) { // TODO(perf): We could binary search here, but... bleh. for (auto& scope: *b) { if (scope.typeId == id) { if (scope.isUnbound) { // Unbound brand parameter. result.scopeId = id; result.paramIndex = index; return; } else if (index >= scope.bindingCount) { // Binding index out-of-range. Treat as AnyPointer. This is important to allow // new type parameters to be added to existing types without breaking dependent // schemas. return; } else { result = scope.bindings[index]; return; } } } return; } else { // Unbound brand parameter. result.scopeId = id; result.paramIndex = index; return; } } case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: result.isImplicitParameter = true; result.paramIndex = anyPointer.getImplicitMethodParameter().getParameterIndex(); return; } KJ_UNREACHABLE; } } KJ_UNREACHABLE; } void SchemaLoader::Impl::makeDep(_::RawBrandedSchema::Binding& result, uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, schema::Brand::Reader brand, kj::StringPtr scopeName, kj::Maybe> brandBindings) { const _::RawSchema* schema; if (typeId == capnp::typeId()) { // StreamResult is a very special type that is used to mark when a method is declared as // streaming ("foo @0 () -> stream;"). We like to auto-load it if we see it as someone's // dependency. schema = loadNative(&_::rawSchema()); } else { schema = loadEmpty(typeId, kj::str("(unknown type; seen as dependency of ", scopeName, ")"), expectedKind, true); } result.which = static_cast(whichType); result.schema = makeBranded(schema, brand, brandBindings); } const _::RawBrandedSchema* SchemaLoader::Impl::makeDepSchema( schema::Type::Reader type, kj::StringPtr scopeName, kj::Maybe> brandBindings) { _::RawBrandedSchema::Binding binding; memset(&binding, 0, sizeof(binding)); makeDep(binding, type, scopeName, brandBindings); return binding.schema; } const _::RawBrandedSchema* SchemaLoader::Impl::makeDepSchema( uint64_t typeId, schema::Type::Which whichType, schema::Node::Which expectedKind, schema::Brand::Reader brand, kj::StringPtr scopeName, kj::Maybe> brandBindings) { _::RawBrandedSchema::Binding binding; memset(&binding, 0, sizeof(binding)); makeDep(binding, typeId, whichType, expectedKind, brand, scopeName, brandBindings); return binding.schema; } template kj::ArrayPtr SchemaLoader::Impl::copyDeduped(kj::ArrayPtr values) { if (values.size() == 0) { return kj::arrayPtr(kj::implicitCast(nullptr), 0); } auto bytes = values.asBytes(); KJ_IF_MAYBE(dupe, dedupTable.find(bytes)) { return kj::arrayPtr(reinterpret_cast(dupe->begin()), values.size()); } // Need to make a new copy. auto copy = arena.allocateArray(values.size()); memcpy(copy.begin(), values.begin(), values.size() * sizeof(T)); dedupTable.insert(copy.asBytes()); return copy; } template kj::ArrayPtr SchemaLoader::Impl::copyDeduped(kj::ArrayPtr values) { return copyDeduped(kj::ArrayPtr(values)); } SchemaLoader::Impl::TryGetResult SchemaLoader::Impl::tryGet(uint64_t typeId) const { KJ_IF_MAYBE(schema, schemas.find(typeId)) { return {*schema, initializer.getCallback()}; } else { return {nullptr, initializer.getCallback()}; } } const _::RawBrandedSchema* SchemaLoader::Impl::getUnbound(const _::RawSchema* schema) { if (!readMessageUnchecked(schema->encodedNode).getIsGeneric()) { // Not a generic type, so just return the default brand. return &schema->defaultBrand; } KJ_IF_MAYBE(existing, unboundBrands.find(schema)) { return *existing; } else { auto slot = &arena.allocate<_::RawBrandedSchema>(); memset(slot, 0, sizeof(*slot)); slot->generic = schema; auto deps = makeBrandedDependencies(schema, nullptr); slot->dependencies = deps.begin(); slot->dependencyCount = deps.size(); unboundBrands.insert(schema, slot); return slot; } } kj::Array SchemaLoader::Impl::getAllLoaded() const { size_t count = 0; for (auto& schema: schemas) { if (schema.value->lazyInitializer == nullptr) ++count; } kj::Array result = kj::heapArray(count); size_t i = 0; for (auto& schema: schemas) { if (schema.value->lazyInitializer == nullptr) { result[i++] = Schema(&schema.value->defaultBrand); } } return result; } void SchemaLoader::Impl::computeOptimizationHints() { kj::HashMap<_::RawSchema*, kj::Vector<_::RawSchema*>> undecided; // This map contains schemas for which we haven't yet decided if they might have capabilities. // They at least do not directly contain capabilities, but they can't be fully decided until // the dependents are decided. // // Each entry maps to a list of other schemas whose decisions depend on this schema. When a // schema in the map is discovered to contain capabilities, then all these dependents must also // be presumed to contain capabilities. // First pass: Decide on the easy cases and populate the `undecided` map with hard cases. for (auto& entry: schemas) { _::RawSchema* schema = entry.value; // Default to assuming everything could contain caps. schema->mayContainCapabilities = true; if (schema->lazyInitializer != nullptr) { // Not initialized yet, so we have to be conservative and assume there could be capabilities. continue; } auto node = readMessageUnchecked(schema->encodedNode); if (!node.isStruct()) { // Non-structs are irrelevant. continue; } auto structSchema = node.getStruct(); bool foundAnyCaps = false; bool foundAnyStructs = false; for (auto field: structSchema.getFields()) { switch (field.which()) { case schema::Field::GROUP: foundAnyStructs = true; break; case schema::Field::SLOT: { auto type = field.getSlot().getType(); while (type.isList()) { type = type.getList().getElementType(); } switch (type.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: case schema::Type::ENUM: // Not a capability. break; case schema::Type::STRUCT: foundAnyStructs = true; break; case schema::Type::ANY_POINTER: // could be a capability, or transitively contain one case schema::Type::INTERFACE: // definitely a capability foundAnyCaps = true; break; case schema::Type::LIST: KJ_UNREACHABLE; // handled above } break; } } if (foundAnyCaps) break; // no point continuing } if (foundAnyCaps) { // Definitely has capabilities, don't add to `undecided`. } else if (!foundAnyStructs) { // Definitely does NOT have capabilities. Go ahead and set the hint and don't add to // `undecided`. schema->mayContainCapabilities = false; } else { // Don't know yet. Mark as no-capabilities for now, but place in `undecided` set to review // later. schema->mayContainCapabilities = false; undecided.insert(schema, {}); } } // Second pass: For all undecided schemas, check dependencies and register as dependents where // needed. kj::Vector<_::RawSchema*> decisions; // Schemas that have become decided. for (auto& entry: undecided) { auto schema = entry.key; auto node = readMessageUnchecked(schema->encodedNode).getStruct(); for (auto field: node.getFields()) { kj::Maybe depId; switch (field.which()) { case schema::Field::GROUP: depId = field.getGroup().getTypeId(); break; case schema::Field::SLOT: { auto type = field.getSlot().getType(); while (type.isList()) { type = type.getList().getElementType(); } if (type.isStruct()) { depId = type.getStruct().getTypeId(); } break; } } KJ_IF_MAYBE(d, depId) { _::RawSchema* dep = KJ_ASSERT_NONNULL(schemas.find(*d)); if (dep->mayContainCapabilities) { // Oops, this dependency is already known to have capabilities. So that means the current // schema also has capabilities, transitively. Mark it as such. schema->mayContainCapabilities = true; // Schedule this schema for removal later. decisions.add(schema); // Might as well end the loop early. break; } else KJ_IF_MAYBE(undecidedEntry, undecided.find(dep)) { // This dependency is in the undecided set. Register interest in it. undecidedEntry->add(schema); } else { // This dependency is decided, and the decision is that it has no capabilities. So it // has no impact on the dependent. } } } } // Third pass: For each decision we made, remove it and propagate to its dependents. while (!decisions.empty()) { _::RawSchema* decision = decisions.back(); decisions.removeLast(); auto& entry = KJ_ASSERT_NONNULL(undecided.findEntry(decision)); for (auto& dependent: entry.value) { if (!dependent->mayContainCapabilities) { // The dependent was not previously decided. But, we now know it has a dependency which has // capabilities, therefore we can decide the dependent. dependent->mayContainCapabilities = true; decisions.add(dependent); } } undecided.erase(entry); } // Everything that is left in `undecided` must only be waiting on other undecided schemas. We // can therefore decide that none of them have any capabilities. We marked them as such // earlier so now we're all done. } void SchemaLoader::Impl::requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount) { structSizeRequirements.upsert(id, { uint16_t(dataWordCount), uint16_t(pointerCount) }, [&](RequiredSize& existingValue, RequiredSize&& newValue) { existingValue.dataWordCount = kj::max(existingValue.dataWordCount, newValue.dataWordCount); existingValue.pointerCount = kj::max(existingValue.pointerCount, newValue.pointerCount); }); KJ_IF_MAYBE(schema, schemas.find(id)) { applyStructSizeRequirement(*schema, dataWordCount, pointerCount); } } kj::ArrayPtr SchemaLoader::Impl::makeUncheckedNode(schema::Node::Reader node) { size_t size = node.totalSize().wordCount + 1; kj::ArrayPtr result = arena.allocateArray(size); memset(result.begin(), 0, size * sizeof(word)); copyToUnchecked(node, result); return result; } kj::ArrayPtr SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirements( schema::Node::Reader node) { if (node.isStruct()) { KJ_IF_MAYBE(requirement, structSizeRequirements.find(node.getId())) { auto structNode = node.getStruct(); if (structNode.getDataWordCount() < requirement->dataWordCount || structNode.getPointerCount() < requirement->pointerCount) { return rewriteStructNodeWithSizes(node, requirement->dataWordCount, requirement->pointerCount); } } } return makeUncheckedNode(node); } kj::ArrayPtr SchemaLoader::Impl::rewriteStructNodeWithSizes( schema::Node::Reader node, uint dataWordCount, uint pointerCount) { MallocMessageBuilder builder; builder.setRoot(node); auto root = builder.getRoot(); auto newStruct = root.getStruct(); newStruct.setDataWordCount(kj::max(newStruct.getDataWordCount(), dataWordCount)); newStruct.setPointerCount(kj::max(newStruct.getPointerCount(), pointerCount)); return makeUncheckedNode(root); } void SchemaLoader::Impl::applyStructSizeRequirement( _::RawSchema* raw, uint dataWordCount, uint pointerCount) { auto node = readMessageUnchecked(raw->encodedNode); auto structNode = node.getStruct(); if (structNode.getDataWordCount() < dataWordCount || structNode.getPointerCount() < pointerCount) { // Sizes need to be increased. Must rewrite. kj::ArrayPtr words = rewriteStructNodeWithSizes(node, dataWordCount, pointerCount); // We don't need to re-validate the node because we know this change could not possibly have // invalidated it. Just remake the unchecked message. raw->encodedNode = words.begin(); raw->encodedSize = words.size(); } } void SchemaLoader::InitializerImpl::init(const _::RawSchema* schema) const { KJ_IF_MAYBE(c, callback) { c->load(loader, schema->id); } if (schema->lazyInitializer != nullptr) { // The callback declined to load a schema. We need to disable the initializer so that it // doesn't get invoked again later, as we can no longer modify this schema once it is in use. // Lock the loader for read to make sure no one is concurrently loading a replacement for this // schema node. auto lock = loader.impl.lockShared(); // Get the mutable version of the schema. _::RawSchema* mutableSchema = lock->get()->tryGet(schema->id).schema; KJ_ASSERT(mutableSchema == schema, "A schema not belonging to this loader used its initializer."); // Disable the initializer. #if __GNUC__ || defined(__clang__) __atomic_store_n(&mutableSchema->lazyInitializer, nullptr, __ATOMIC_RELEASE); __atomic_store_n(&mutableSchema->defaultBrand.lazyInitializer, nullptr, __ATOMIC_RELEASE); #elif _MSC_VER std::atomic_thread_fence(std::memory_order_release); *static_cast<_::RawSchema::Initializer const* volatile*>( &mutableSchema->lazyInitializer) = nullptr; *static_cast<_::RawBrandedSchema::Initializer const* volatile*>( &mutableSchema->defaultBrand.lazyInitializer) = nullptr; #else #error "Platform not supported" #endif } } void SchemaLoader::BrandedInitializerImpl::init(const _::RawBrandedSchema* schema) const { schema->generic->ensureInitialized(); auto lock = loader.impl.lockExclusive(); if (schema->lazyInitializer == nullptr) { // Never mind, someone beat us to it. return; } // Get the mutable version. _::RawBrandedSchema* mutableSchema = KJ_ASSERT_NONNULL( lock->get()->brands.find(SchemaBindingsPair { schema->generic, schema->scopes })); KJ_ASSERT(mutableSchema == schema); // Construct its dependency map. auto deps = lock->get()->makeBrandedDependencies(mutableSchema->generic, kj::arrayPtr(mutableSchema->scopes, mutableSchema->scopeCount)); mutableSchema->dependencies = deps.begin(); mutableSchema->dependencyCount = deps.size(); // It's initialized now, so disable the initializer. #if __GNUC__ || defined(__clang__) __atomic_store_n(&mutableSchema->lazyInitializer, nullptr, __ATOMIC_RELEASE); #elif _MSC_VER std::atomic_thread_fence(std::memory_order_release); *static_cast<_::RawBrandedSchema::Initializer const* volatile*>( &mutableSchema->lazyInitializer) = nullptr; #else #error "Platform not supported" #endif } // ======================================================================================= SchemaLoader::SchemaLoader(): impl(kj::heap(*this)) {} SchemaLoader::SchemaLoader(const LazyLoadCallback& callback) : impl(kj::heap(*this, callback)) {} SchemaLoader::~SchemaLoader() noexcept(false) {} Schema SchemaLoader::get(uint64_t id, schema::Brand::Reader brand, Schema scope) const { KJ_IF_MAYBE(result, tryGet(id, brand, scope)) { return *result; } else { KJ_FAIL_REQUIRE("no schema node loaded for id", kj::hex(id)); } } kj::Maybe SchemaLoader::tryGet( uint64_t id, schema::Brand::Reader brand, Schema scope) const { auto getResult = impl.lockShared()->get()->tryGet(id); if (getResult.schema == nullptr || getResult.schema->lazyInitializer != nullptr) { // This schema couldn't be found or has yet to be lazily loaded. If we have a lazy loader // callback, invoke it now to try to get it to load this schema. KJ_IF_MAYBE(c, getResult.callback) { c->load(*this, id); } getResult = impl.lockShared()->get()->tryGet(id); } if (getResult.schema != nullptr && getResult.schema->lazyInitializer == nullptr) { if (brand.getScopes().size() > 0) { auto brandedSchema = impl.lockExclusive()->get()->makeBranded( getResult.schema, brand, scope.raw->isUnbound() ? kj::Maybe>(nullptr) : kj::arrayPtr(scope.raw->scopes, scope.raw->scopeCount)); brandedSchema->ensureInitialized(); return Schema(brandedSchema); } else { return Schema(&getResult.schema->defaultBrand); } } else { return nullptr; } } Schema SchemaLoader::getUnbound(uint64_t id) const { auto schema = get(id); return Schema(impl.lockExclusive()->get()->getUnbound(schema.raw->generic)); } Type SchemaLoader::getType(schema::Type::Reader proto, Schema scope) const { switch (proto.which()) { case schema::Type::VOID: case schema::Type::BOOL: case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: case schema::Type::FLOAT32: case schema::Type::FLOAT64: case schema::Type::TEXT: case schema::Type::DATA: return proto.which(); case schema::Type::STRUCT: { auto structType = proto.getStruct(); return get(structType.getTypeId(), structType.getBrand(), scope).asStruct(); } case schema::Type::ENUM: { auto enumType = proto.getEnum(); return get(enumType.getTypeId(), enumType.getBrand(), scope).asEnum(); } case schema::Type::INTERFACE: { auto interfaceType = proto.getInterface(); return get(interfaceType.getTypeId(), interfaceType.getBrand(), scope) .asInterface(); } case schema::Type::LIST: return ListSchema::of(getType(proto.getList().getElementType(), scope)); case schema::Type::ANY_POINTER: { auto anyPointer = proto.getAnyPointer(); switch (anyPointer.which()) { case schema::Type::AnyPointer::UNCONSTRAINED: return schema::Type::ANY_POINTER; case schema::Type::AnyPointer::PARAMETER: { auto param = anyPointer.getParameter(); return scope.getBrandBinding(param.getScopeId(), param.getParameterIndex()); } case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: // We don't support binding implicit method params here. return schema::Type::ANY_POINTER; } KJ_UNREACHABLE; } } KJ_UNREACHABLE; } Schema SchemaLoader::load(const schema::Node::Reader& reader) { return Schema(&impl.lockExclusive()->get()->load(reader, false)->defaultBrand); } Schema SchemaLoader::loadOnce(const schema::Node::Reader& reader) const { auto locked = impl.lockExclusive(); auto getResult = locked->get()->tryGet(reader.getId()); if (getResult.schema == nullptr || getResult.schema->lazyInitializer != nullptr) { // Doesn't exist yet, or the existing schema is a placeholder and therefore has not yet been // seen publicly. Go ahead and load the incoming reader. return Schema(&locked->get()->load(reader, false)->defaultBrand); } else { return Schema(&getResult.schema->defaultBrand); } } kj::Array SchemaLoader::getAllLoaded() const { return impl.lockShared()->get()->getAllLoaded(); } void SchemaLoader::computeOptimizationHints() { impl.lockExclusive()->get()->computeOptimizationHints(); } void SchemaLoader::loadNative(const _::RawSchema* nativeSchema) { impl.lockExclusive()->get()->loadNative(nativeSchema); } } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc.h0000644000175000017500000007305414712011043017571 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include "rpc-prelude.h" CAPNP_BEGIN_HEADER namespace kj { class AutoCloseFd; } namespace capnp { template class VatNetwork; template class SturdyRefRestorer; class MessageReader; template class BootstrapFactory: public _::BootstrapFactoryBase { // Interface that constructs per-client bootstrap interfaces. Use this if you want each client // who connects to see a different bootstrap interface based on their (authenticated) VatId. // This allows an application to bootstrap off of the authentication performed at the VatNetwork // level. (Typically VatId is some sort of public key.) // // This is only useful for multi-party networks. For TwoPartyVatNetwork, there's no reason to // use a BootstrapFactory; just specify a single bootstrap capability in this case. public: virtual Capability::Client createFor(typename VatId::Reader clientId) = 0; // Create a bootstrap capability appropriate for exposing to the given client. VatNetwork will // have authenticated the client VatId before this is called. private: Capability::Client baseCreateFor(AnyStruct::Reader clientId) override; }; template class RpcSystem: public _::RpcSystemBase { // Represents the RPC system, which is the portal to objects available on the network. // // The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork` // determines how to form connections between vats -- specifically, two-way, private, reliable, // sequenced datagram connections. The RPC implementation determines how to use such connections // to manage object references and make method calls. // // See `makeRpcServer()` and `makeRpcClient()` below for convenient syntax for setting up an // `RpcSystem` given a `VatNetwork`. // // See `ez-rpc.h` for an even simpler interface for setting up RPC in a typical two-party // client/server scenario. public: template RpcSystem( VatNetwork& network, kj::Maybe bootstrapInterface); template RpcSystem( VatNetwork& network, BootstrapFactory& bootstrapFactory); template RpcSystem( VatNetwork& network, SturdyRefRestorer& restorer); RpcSystem(RpcSystem&& other) = default; Capability::Client bootstrap(typename VatId::Reader vatId); // Connect to the given vat and return its bootstrap interface. Capability::Client restore(typename VatId::Reader hostId, AnyPointer::Reader objectId) CAPNP_DEPRECATED("Please transition to using a bootstrap interface instead."); // ** DEPRECATED ** // // Restores the given SturdyRef from the network and return the capability representing it. // // `hostId` identifies the host from which to request the ref, in the format specified by the // `VatNetwork` in use. `objectId` is the object ID in whatever format is expected by said host. // // This method will be removed in a future version of Cap'n Proto. Instead, please transition // to using bootstrap(), which is equivalent to calling restore() with a null `objectId`. // You may emulate the old concept of object IDs by exporting a bootstrap interface which has // methods that can be used to obtain other capabilities by ID. void setFlowLimit(size_t words); // Sets the incoming call flow limit. If more than `words` worth of call messages have not yet // received responses, the RpcSystem will not read further messages from the stream. This can be // used as a crude way to prevent a resource exhaustion attack (or bug) in which a peer makes an // excessive number of simultaneous calls that consume the receiver's RAM. // // There are some caveats. When over the flow limit, all messages are blocked, including returns. // If the outstanding calls are themselves waiting on calls going in the opposite direction, the // flow limit may prevent those calls from completing, leading to deadlock. However, a // sufficiently high limit should make this unlikely. // // Note that a call's parameter size counts against the flow limit until the call returns, even // if the recipient calls releaseParams() to free the parameter memory early. This is because // releaseParams() may simply indicate that the parameters have been forwarded to another // machine, but are still in-memory there. For illustration, say that Alice made a call to Bob // who forwarded the call to Carol. Bob has imposed a flow limit on Alice. Alice's calls are // being forwarded to Carol, so Bob never keeps the parameters in-memory for more than a brief // period. However, the flow limit counts all calls that haven't returned, even if Bob has // already freed the memory they consumed. You might argue that the right solution here is // instead for Carol to impose her own flow limit on Bob. This has a serious problem, though: // Bob might be forwarding requests to Carol on behalf of many different parties, not just Alice. // If Alice can pump enough data to hit the Bob -> Carol flow limit, then those other parties // will be disrupted. Thus, we can only really impose the limit on the Alice -> Bob link, which // only affects Alice. We need that one flow limit to limit Alice's impact on the whole system, // so it has to count all in-flight calls. // // In Sandstorm, flow limits are imposed by the supervisor on calls coming out of a grain, in // order to prevent a grain from inundating the system with in-flight calls. In practice, the // main time this happens is when a grain is pushing a large file download and doesn't implement // proper cooperative flow control. // void setTraceEncoder(kj::Function func); // // (Inherited from _::RpcSystemBase) // // Set a function to call to encode exception stack traces for transmission to remote parties. // By default, traces are not transmitted at all. If a callback is provided, then the returned // string will be sent with the exception. If the remote end is KJ/C++ based, then this trace // text ends up being accessible as kj::Exception::getRemoteTrace(). // // Stack traces can sometimes contain sensitive information, so you should think carefully about // what information you are willing to reveal to the remote party. kj::Promise run() { return RpcSystemBase::run(); } // Listens for incoming RPC connections and handles them. Never returns normally, but could throw // an exception if the system becomes unable to accept new connections (e.g. because the // underlying listen socket becomes broken somehow). // // For historical reasons, the RpcSystem will actually run itself even if you do not call this. // However, if an exception is thrown, the RpcSystem will log the exception to the console and // then cease accepting new connections. In this case, your server may be in a broken state, but // without restarting. All servers should therefore call run() and handle failures in some way. }; template RpcSystem makeRpcServer( VatNetwork& network, Capability::Client bootstrapInterface); // Make an RPC server. Typical usage (e.g. in a main() function): // // MyEventLoop eventLoop; // kj::WaitScope waitScope(eventLoop); // MyNetwork network; // MyMainInterface::Client bootstrap = makeMain(); // auto server = makeRpcServer(network, bootstrap); // kj::NEVER_DONE.wait(waitScope); // run forever // // See also ez-rpc.h, which has simpler instructions for the common case of a two-party // client-server RPC connection. template RpcSystem makeRpcServer( VatNetwork& network, BootstrapFactory& bootstrapFactory); // Make an RPC server that can serve different bootstrap interfaces to different clients via a // BootstrapInterface. template RpcSystem makeRpcServer( VatNetwork& network, SturdyRefRestorer& restorer) CAPNP_DEPRECATED("Please transition to using a bootstrap interface instead."); // ** DEPRECATED ** // // Create an RPC server which exports multiple main interfaces by object ID. The `restorer` object // can be used to look up objects by ID. // // Please transition to exporting only one interface, which is known as the "bootstrap" interface. // For backwards-compatibility with old clients, continue to implement SturdyRefRestorer, but // return the new bootstrap interface when the request object ID is null. When new clients connect // and request the bootstrap interface, they will get that interface. Eventually, once all clients // are updated to request only the bootstrap interface, stop implementing SturdyRefRestorer and // switch to passing the bootstrap capability itself as the second parameter to `makeRpcServer()`. template RpcSystem makeRpcClient( VatNetwork& network); // Make an RPC client. Typical usage (e.g. in a main() function): // // MyEventLoop eventLoop; // kj::WaitScope waitScope(eventLoop); // MyNetwork network; // auto client = makeRpcClient(network); // MyCapability::Client cap = client.restore(hostId, objId).castAs(); // auto response = cap.fooRequest().send().wait(waitScope); // handleMyResponse(response); // // See also ez-rpc.h, which has simpler instructions for the common case of a two-party // client-server RPC connection. template class SturdyRefRestorer: public _::SturdyRefRestorerBase { // ** DEPRECATED ** // // In Cap'n Proto 0.4.x, applications could export multiple main interfaces identified by // object IDs. The callback used to map object IDs to objects was `SturdyRefRestorer`, as we // imagined this would eventually be used for restoring SturdyRefs as well. In practice, it was // never used for real SturdyRefs, only for exporting singleton objects under well-known names. // // The new preferred strategy is to export only a _single_ such interface, called the // "bootstrap interface". That interface can itself have methods for obtaining other objects, of // course, but that is up to the app. `SturdyRefRestorer` exists for backwards-compatibility. // // Hint: Use SturdyRefRestorer to define a server that exports services under // string names. public: virtual Capability::Client restore(typename SturdyRefObjectId::Reader ref) CAPNP_DEPRECATED( "Please transition to using bootstrap interfaces instead of SturdyRefRestorer.") = 0; // Restore the given object, returning a capability representing it. private: Capability::Client baseRestore(AnyPointer::Reader ref) override final; }; // ======================================================================================= // VatNetwork class OutgoingRpcMessage { // A message to be sent by a `VatNetwork`. public: virtual AnyPointer::Builder getBody() = 0; // Get the message body, which the caller may fill in any way it wants. (The standard RPC // implementation initializes it as a Message as defined in rpc.capnp.) virtual void setFds(kj::Array fds) {} // Set the list of file descriptors to send along with this message, if FD passing is supported. // An implementation may ignore this. virtual void send() = 0; // Send the message, or at least put it in a queue to be sent later. Note that the builder // returned by `getBody()` remains valid at least until the `OutgoingRpcMessage` is destroyed. virtual size_t sizeInWords() = 0; // Get the total size of the message, for flow control purposes. Although the caller could // also call getBody().targetSize(), doing that would walk the message tree, whereas typical // implementations can compute the size more cheaply by summing segment sizes. }; class IncomingRpcMessage { // A message received from a `VatNetwork`. public: virtual AnyPointer::Reader getBody() = 0; // Get the message body, to be interpreted by the caller. (The standard RPC implementation // interprets it as a Message as defined in rpc.capnp.) virtual kj::ArrayPtr getAttachedFds() { return nullptr; } // If the transport supports attached file descriptors and some were attached to this message, // returns them. Otherwise returns an empty array. It is intended that the caller will move the // FDs out of this table when they are consumed, possibly leaving behind a null slot. Callers // should be careful to check if an FD was already consumed by comparing the slot with `nullptr`. // (We don't use Maybe here because moving from a Maybe doesn't make it null, so it would only // add confusion. Moving from an AutoCloseFd does in fact make it null.) virtual size_t sizeInWords() = 0; // Get the total size of the message, for flow control purposes. Although the caller could // also call getBody().targetSize(), doing that would walk the message tree, whereas typical // implementations can compute the size more cheaply by summing segment sizes. static bool isShortLivedRpcMessage(AnyPointer::Reader body); // Helper function which computes whether the standard RpcSystem implementation would consider // the given message body to be short-lived, meaning it will be dropped before the next message // is read. This is useful to implement BufferedMessageStream::IsShortLivedCallback. static kj::Function getShortLivedCallback(); // Returns a function that wraps isShortLivedRpcMessage(). The returned function type matches // `BufferedMessageStream::IsShortLivedCallback` (defined in serialize-async.h), but we don't // include that header here. }; class RpcFlowController { // Tracks a particular RPC stream in order to implement a flow control algorithm. public: virtual kj::Promise send(kj::Own message, kj::Promise ack) = 0; // Like calling message->send(), but the promise resolves when it's a good time to send the // next message. // // `ack` is a promise that resolves when the message has been acknowledged from the other side. // In practice, `message` is typically a `Call` message and `ack` is a `Return`. Note that this // means `ack` counts not only time to transmit the message but also time for the remote // application to process the message. The flow controller is expected to apply backpressure if // the remote application responds slowly. If `ack` rejects, then all outstanding and future // sends will propagate the exception. // // Note that messages sent with this method must still be delivered in the same order as if they // had been sent with `message->send()`; they cannot be delayed until later. This is important // because the message may introduce state changes in the RPC system that later messages rely on, // such as introducing a new Question ID that a later message may reference. Thus, the controller // can only create backpressure by having the returned promise resolve slowly. // // Dropping the returned promise does not cancel the send. Once send() is called, there's no way // to stop it. virtual kj::Promise waitAllAcked() = 0; // Wait for all `ack`s previously passed to send() to finish. It is an error to call send() again // after this. // --------------------------------------------------------------------------- // Common implementations. static kj::Own newFixedWindowController(size_t windowSize); // Constructs a flow controller that implements a strict fixed window of the given size. In other // words, the controller will throttle the stream when the total bytes in-flight exceeds the // window. class WindowGetter { public: virtual size_t getWindow() = 0; }; static kj::Own newVariableWindowController(WindowGetter& getter); // Like newFixedWindowController(), but the window size is allowed to vary over time. Useful if // you have a technique for estimating one good window size for the connection as a whole but not // for individual streams. Keep in mind, though, that in situations where the other end of the // connection is merely proxying capabilities from a variety of final destinations across a // variety of networks, no single window will be appropriate for all streams. static constexpr size_t DEFAULT_WINDOW_SIZE = 65536; // The window size used by the default implementation of Connection::newStream(). }; template class VatNetwork: public _::VatNetworkBase { // Cap'n Proto RPC operates between vats, where a "vat" is some sort of host of objects. // Typically one Cap'n Proto process (in the Unix sense) is one vat. The RPC system is what // allows calls between objects hosted in different vats. // // The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork` // determines how to form connections between vats -- specifically, two-way, private, reliable, // sequenced datagram connections. The RPC implementation determines how to use such connections // to manage object references and make method calls. // // The most common implementation of VatNetwork is TwoPartyVatNetwork (rpc-twoparty.h). Most // simple client-server apps will want to use it. (You may even want to use the EZ RPC // interfaces in `ez-rpc.h` and avoid all of this.) // // TODO(someday): Provide a standard implementation for the public internet. public: class Connection; struct ConnectionAndProvisionId { // Result of connecting to a vat introduced by another vat. kj::Own connection; // Connection to the new vat. kj::Own firstMessage; // An already-allocated `OutgoingRpcMessage` associated with `connection`. The RPC system will // construct this as an `Accept` message and send it. Orphan provisionId; // A `ProvisionId` already allocated inside `firstMessage`, which the RPC system will use to // build the `Accept` message. }; class Connection: public _::VatNetworkBase::Connection { // A two-way RPC connection. // // This object may represent a connection that doesn't exist yet, but is expected to exist // in the future. In this case, sent messages will automatically be queued and sent once the // connection is ready, so that the caller doesn't need to know the difference. public: virtual kj::Own newStream() override { return RpcFlowController::newFixedWindowController(65536); } // Construct a flow controller for a new stream on this connection. The controller can be // passed into OutgoingRpcMessage::sendStreaming(). // // The default implementation returns a dummy stream controller that just applies a fixed // window of 64k to everything. This always works but may constrain throughput on networks // where the bandwidth-delay product is high, while conversely providing too much buffer when // the bandwidth-delay product is low. // // WARNING: The RPC system may keep the `RpcFlowController` object alive past the lifetime of // the `Connection` itself. However, it will not call `send()` any more after the // `Connection` is destroyed. // // TODO(perf): We should introduce a flow controller implementation that uses a clock to // measure RTT and bandwidth and dynamically update the window size, like BBR. // Level 0 features ---------------------------------------------- virtual typename VatId::Reader getPeerVatId() = 0; // Returns the connected vat's authenticated VatId. It is the VatNetwork's responsibility to // authenticate this, so that the caller can be assured that they are really talking to the // identified vat and not an imposter. virtual kj::Own newOutgoingMessage(uint firstSegmentWordSize) override = 0; // Allocate a new message to be sent on this connection. // // If `firstSegmentWordSize` is non-zero, it should be treated as a hint suggesting how large // to make the first segment. This is entirely a hint and the connection may adjust it up or // down. If it is zero, the connection should choose the size itself. // // WARNING: The RPC system may keep the `OutgoingRpcMessage` object alive past the lifetime of // the `Connection` itself. However, it will not call `send()` any more after the // `Connection` is destroyed. virtual kj::Promise>> receiveIncomingMessage() override = 0; // Wait for a message to be received and return it. If the read stream cleanly terminates, // return null. If any other problem occurs, throw an exception. // // WARNING: The RPC system may keep the `IncomingRpcMessage` object alive past the lifetime of // the `Connection` itself. virtual kj::Promise shutdown() override KJ_WARN_UNUSED_RESULT = 0; // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The // returned promise resolves after shutdown is complete. private: AnyStruct::Reader baseGetPeerVatId() override; }; // Level 0 features ------------------------------------------------ virtual kj::Maybe> connect(typename VatId::Reader hostId) = 0; // Connect to a VatId. Note that this method immediately returns a `Connection`, even // if the network connection has not yet been established. Messages can be queued to this // connection and will be delivered once it is open. The caller must attempt to read from the // connection to verify that it actually succeeded; the read will fail if the connection // couldn't be opened. Some network implementations may actually start sending messages before // hearing back from the server at all, to avoid a round trip. // // Returns nullptr if `hostId` refers to the local host. virtual kj::Promise> accept() = 0; // Wait for the next incoming connection and return it. // Level 4 features ------------------------------------------------ // TODO(someday) private: kj::Maybe> baseConnect(AnyStruct::Reader hostId) override final; kj::Promise> baseAccept() override final; }; // ======================================================================================= // *************************************************************************************** // Inline implementation details start here // *************************************************************************************** // ======================================================================================= template Capability::Client BootstrapFactory::baseCreateFor(AnyStruct::Reader clientId) { return createFor(clientId.as()); } template kj::Maybe> VatNetwork:: baseConnect(AnyStruct::Reader ref) { auto maybe = connect(ref.as()); return maybe.map([](kj::Own& conn) -> kj::Own<_::VatNetworkBase::Connection> { return kj::mv(conn); }); } template kj::Promise> VatNetwork::baseAccept() { return accept().then( [](kj::Own&& connection) -> kj::Own<_::VatNetworkBase::Connection> { return kj::mv(connection); }); } template AnyStruct::Reader VatNetwork< SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>:: Connection::baseGetPeerVatId() { return getPeerVatId(); } template Capability::Client SturdyRefRestorer::baseRestore(AnyPointer::Reader ref) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" return restore(ref.getAs()); #pragma GCC diagnostic pop } template template RpcSystem::RpcSystem( VatNetwork& network, kj::Maybe bootstrap) : _::RpcSystemBase(network, kj::mv(bootstrap)) {} template template RpcSystem::RpcSystem( VatNetwork& network, BootstrapFactory& bootstrapFactory) : _::RpcSystemBase(network, bootstrapFactory) {} template template RpcSystem::RpcSystem( VatNetwork& network, SturdyRefRestorer& restorer) : _::RpcSystemBase(network, restorer) {} template Capability::Client RpcSystem::bootstrap(typename VatId::Reader vatId) { return baseBootstrap(_::PointerHelpers::getInternalReader(vatId)); } template Capability::Client RpcSystem::restore( typename VatId::Reader hostId, AnyPointer::Reader objectId) { return baseRestore(_::PointerHelpers::getInternalReader(hostId), objectId); } template inline void RpcSystem::setFlowLimit(size_t words) { baseSetFlowLimit(words); } template RpcSystem makeRpcServer( VatNetwork& network, Capability::Client bootstrapInterface) { return RpcSystem(network, kj::mv(bootstrapInterface)); } template RpcSystem makeRpcServer( VatNetwork& network, BootstrapFactory& bootstrapFactory) { return RpcSystem(network, bootstrapFactory); } template RpcSystem makeRpcServer( VatNetwork& network, SturdyRefRestorer& restorer) { return RpcSystem(network, restorer); } template RpcSystem makeRpcClient( VatNetwork& network) { return RpcSystem(network, nullptr); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/test-util.h0000644000175000017500000002675614731420004020750 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include "blob.h" #include #if !CAPNP_LITE #include "dynamic.h" #include #endif // !CAPNP_LITE CAPNP_BEGIN_HEADER // TODO(cleanup): Auto-generate stringification functions for union discriminants. namespace capnproto_test { namespace capnp { namespace test { inline kj::String KJ_STRINGIFY(TestUnion::Union0::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestUnion::Union1::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestUnion::Union2::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestUnion::Union3::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestUnnamedUnion::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestGroups::Groups::Which which) { return kj::str(static_cast(which)); } inline kj::String KJ_STRINGIFY(TestInterleavedGroups::Group1::Which which) { return kj::str(static_cast(which)); } } // namespace test } // namespace capnp } // namespace capnproto_test namespace capnp { namespace _ { // private inline Data::Reader data(const char* str) { return Data::Reader(reinterpret_cast(str), strlen(str)); } namespace test = capnproto_test::capnp::test; // We don't use "using namespace" to pull these in because then things would still compile // correctly if they were generated in the global namespace. using ::capnproto_test::capnp::test::TestAllTypes; using ::capnproto_test::capnp::test::TestDefaults; using ::capnproto_test::capnp::test::TestEnum; using ::capnproto_test::capnp::test::TestUnion; using ::capnproto_test::capnp::test::TestUnionDefaults; using ::capnproto_test::capnp::test::TestNestedTypes; using ::capnproto_test::capnp::test::TestUsing; using ::capnproto_test::capnp::test::TestListDefaults; using ::capnproto_test::capnp::test::TestInterleavedGroups; void initTestMessage(TestAllTypes::Builder builder); void initTestMessage(TestDefaults::Builder builder); void initTestMessage(TestListDefaults::Builder builder); void checkTestMessage(TestAllTypes::Builder builder); void checkTestMessage(TestDefaults::Builder builder); void checkTestMessage(TestListDefaults::Builder builder); void checkTestMessage(TestAllTypes::Reader reader); void checkTestMessage(TestDefaults::Reader reader); void checkTestMessage(TestListDefaults::Reader reader); void checkTestMessageAllZero(TestAllTypes::Builder builder); void checkTestMessageAllZero(TestAllTypes::Reader reader); #if !CAPNP_LITE void initDynamicTestMessage(DynamicStruct::Builder builder); void initDynamicTestLists(DynamicStruct::Builder builder); void checkDynamicTestMessage(DynamicStruct::Builder builder); void checkDynamicTestLists(DynamicStruct::Builder builder); void checkDynamicTestMessage(DynamicStruct::Reader reader); void checkDynamicTestLists(DynamicStruct::Reader reader); void checkDynamicTestMessageAllZero(DynamicStruct::Builder builder); void checkDynamicTestMessageAllZero(DynamicStruct::Reader reader); #endif // !CAPNP_LITE template inline void checkElement(T a, T b) { EXPECT_EQ(a, b); } template <> inline void checkElement(float a, float b) { EXPECT_FLOAT_EQ(a, b); } template <> inline void checkElement(double a, double b) { EXPECT_DOUBLE_EQ(a, b); } template void checkList(T reader, std::initializer_list expected) { ASSERT_EQ(expected.size(), reader.size()); for (uint i = 0; i < expected.size(); i++) { checkElement(expected.begin()[i], reader[i]); } } template void checkList(T reader, std::initializer_list expected) { ASSERT_EQ(expected.size(), reader.size()); for (uint i = 0; i < expected.size(); i++) { checkElement(expected.begin()[i], reader[i]); } } inline void checkList(List::Reader reader, std::initializer_list expectedData, std::initializer_list expectedPointers) { ASSERT_EQ(expectedData.size(), reader.size()); for (uint i = 0; i < expectedData.size(); i++) { EXPECT_EQ(expectedData.begin()[i], reader[i].getOld1()); EXPECT_EQ(expectedPointers.begin()[i], reader[i].getOld2()); } } // Hack because as<>() is a template-parameter-dependent lookup everywhere below... #define as template as template void expectPrimitiveEq(T a, T b) { EXPECT_EQ(a, b); } inline void expectPrimitiveEq(float a, float b) { EXPECT_FLOAT_EQ(a, b); } inline void expectPrimitiveEq(double a, double b) { EXPECT_DOUBLE_EQ(a, b); } inline void expectPrimitiveEq(Text::Reader a, Text::Builder b) { EXPECT_EQ(a, b); } inline void expectPrimitiveEq(Data::Reader a, Data::Builder b) { EXPECT_EQ(a, b); } #if !CAPNP_LITE template void checkList(T reader, std::initializer_list> expected) { auto list = reader.as(); ASSERT_EQ(expected.size(), list.size()); for (uint i = 0; i < expected.size(); i++) { expectPrimitiveEq(expected.begin()[i], list[i].as()); } auto typed = reader.as>(); ASSERT_EQ(expected.size(), typed.size()); for (uint i = 0; i < expected.size(); i++) { expectPrimitiveEq(expected.begin()[i], typed[i]); } } #endif // !CAPNP_LITE #undef as // ======================================================================================= // Interface implementations. #if !CAPNP_LITE class TestInterfaceImpl final: public test::TestInterface::Server { public: TestInterfaceImpl(int& callCount); kj::Promise foo(FooContext context) override; kj::Promise baz(BazContext context) override; private: int& callCount; }; class TestExtendsImpl final: public test::TestExtends2::Server { public: TestExtendsImpl(int& callCount); kj::Promise foo(FooContext context) override; kj::Promise grault(GraultContext context) override; private: int& callCount; }; class TestPipelineImpl final: public test::TestPipeline::Server { public: TestPipelineImpl(int& callCount); kj::Promise getCap(GetCapContext context) override; kj::Promise getAnyCap(GetAnyCapContext context) override; kj::Promise getCapPipelineOnly(GetCapPipelineOnlyContext context) override; private: int& callCount; }; class TestCallOrderImpl final: public test::TestCallOrder::Server { public: kj::Promise getCallSequence(GetCallSequenceContext context) override; uint getCount() { return count; } private: uint count = 0; }; class TestTailCallerImpl final: public test::TestTailCaller::Server { public: TestTailCallerImpl(int& callCount); kj::Promise foo(FooContext context) override; private: int& callCount; }; class TestTailCalleeImpl final: public test::TestTailCallee::Server { public: TestTailCalleeImpl(int& callCount); kj::Promise foo(FooContext context) override; private: int& callCount; }; class TestMoreStuffImpl final: public test::TestMoreStuff::Server { public: TestMoreStuffImpl(int& callCount, int& handleCount); kj::Promise getCallSequence(GetCallSequenceContext context) override; kj::Promise callFoo(CallFooContext context) override; kj::Promise callFooWhenResolved(CallFooWhenResolvedContext context) override; kj::Promise neverReturn(NeverReturnContext context) override; kj::Promise hold(HoldContext context) override; kj::Promise callHeld(CallHeldContext context) override; kj::Promise getHeld(GetHeldContext context) override; kj::Promise echo(EchoContext context) override; kj::Promise expectCancel(ExpectCancelContext context) override; kj::Promise getHandle(GetHandleContext context) override; kj::Promise getNull(GetNullContext context) override; kj::Promise getEnormousString(GetEnormousStringContext context) override; kj::Promise writeToFd(WriteToFdContext context) override; kj::Promise throwException(ThrowExceptionContext context) override; kj::Promise throwRemoteException(ThrowRemoteExceptionContext context) override; private: int& callCount; int& handleCount; test::TestInterface::Client clientToHold = nullptr; kj::Promise loop(uint depth, test::TestInterface::Client cap, ExpectCancelContext context); }; class TestCapDestructor final: public test::TestInterface::Server { // Implementation of TestInterface that notifies when it is destroyed. public: TestCapDestructor(kj::Own>&& fulfiller) : fulfiller(kj::mv(fulfiller)), impl(dummy) {} ~TestCapDestructor() { fulfiller->fulfill(); } kj::Promise foo(FooContext context) { return impl.foo(context); } private: kj::Own> fulfiller; int dummy = 0; TestInterfaceImpl impl; }; class TestFdCap final: public test::TestInterface::Server { // Implementation of TestInterface that wraps a file descriptor. public: TestFdCap(kj::AutoCloseFd fd): fd(kj::mv(fd)) {} kj::Maybe getFd() override { return fd.get(); } private: kj::AutoCloseFd fd; }; class TestStreamingImpl final: public test::TestStreaming::Server { public: uint iSum = 0; uint jSum = 0; kj::Maybe>> fulfiller; bool jShouldThrow = false; kj::Promise doStreamI(DoStreamIContext context) override { iSum += context.getParams().getI(); auto paf = kj::newPromiseAndFulfiller(); fulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } kj::Promise doStreamJ(DoStreamJContext context) override { jSum += context.getParams().getJ(); if (jShouldThrow) { KJ_FAIL_ASSERT("throw requested") { break; } return kj::READY_NOW; } auto paf = kj::newPromiseAndFulfiller(); fulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } kj::Promise finishStream(FinishStreamContext context) override { auto results = context.getResults(); results.setTotalI(iSum); results.setTotalJ(jSum); return kj::READY_NOW; } }; #endif // !CAPNP_LITE } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/ez-rpc-test.c++0000644000175000017500000000531614712011043021277 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #include "ez-rpc.h" #include "test-util.h" #include namespace capnp { namespace _ { namespace { TEST(EzRpc, Basic) { int callCount = 0; EzRpcServer server(kj::heap(callCount), "localhost"); EzRpcClient client("localhost", server.getPort().wait(server.getWaitScope())); auto cap = client.getMain(); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); EXPECT_EQ(0, callCount); auto response = request.send().wait(server.getWaitScope()); EXPECT_EQ("foo", response.getX()); EXPECT_EQ(1, callCount); } TEST(EzRpc, DeprecatedNames) { EzRpcServer server("localhost"); int callCount = 0; server.exportCap("cap1", kj::heap(callCount)); server.exportCap("cap2", kj::heap()); EzRpcClient client("localhost", server.getPort().wait(server.getWaitScope())); auto cap = client.importCap("cap1"); auto request = cap.fooRequest(); request.setI(123); request.setJ(true); EXPECT_EQ(0, callCount); auto response = request.send().wait(server.getWaitScope()); EXPECT_EQ("foo", response.getX()); EXPECT_EQ(1, callCount); EXPECT_EQ(0, client.importCap("cap2").castAs() .getCallSequenceRequest().send().wait(server.getWaitScope()).getN()); EXPECT_EQ(1, client.importCap("cap2").castAs() .getCallSequenceRequest().send().wait(server.getWaitScope()).getN()); } } // namespace } // namespace _ } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema-parser.c++0000644000175000017500000003651714712011043021663 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "schema-parser.h" #include "message.h" #include #include #include #include #include #include #include #include #include #include #include namespace capnp { namespace { template size_t findLargestElementBefore(const kj::Vector& vec, const T& key) { KJ_REQUIRE(vec.size() > 0 && vec[0] <= key); size_t lower = 0; size_t upper = vec.size(); while (upper - lower > 1) { size_t mid = (lower + upper) / 2; if (vec[mid] > key) { upper = mid; } else { lower = mid; } } return lower; } } // namespace // ======================================================================================= class SchemaParser::ModuleImpl final: public compiler::Module { public: ModuleImpl(const SchemaParser& parser, kj::Own&& file) : parser(parser), file(kj::mv(file)) {} kj::StringPtr getSourceName() override { return file->getDisplayName(); } Orphan loadContent(Orphanage orphanage) override { kj::Array content = file->readContent(); lineBreaks.get([&](kj::SpaceFor>& space) { auto vec = space.construct(content.size() / 40); vec->add(0); for (const char* pos = content.begin(); pos < content.end(); ++pos) { if (*pos == '\n') { vec->add(pos + 1 - content.begin()); } } return vec; }); MallocMessageBuilder lexedBuilder; auto statements = lexedBuilder.initRoot(); compiler::lex(content, statements, *this); auto parsed = orphanage.newOrphan(); compiler::parseFile(statements.getStatements(), parsed.get(), *this, parser.fileIdsRequired); return parsed; } kj::Maybe importRelative(kj::StringPtr importPath) override { KJ_IF_MAYBE(importedFile, file->import(importPath)) { return parser.getModuleImpl(kj::mv(*importedFile)); } else { return nullptr; } } kj::Maybe> embedRelative(kj::StringPtr embedPath) override { KJ_IF_MAYBE(importedFile, file->import(embedPath)) { return importedFile->get()->readContent().releaseAsBytes(); } else { return nullptr; } } void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override { auto& lines = lineBreaks.get( [](kj::SpaceFor>& space) { KJ_FAIL_REQUIRE("Can't report errors until loadContent() is called."); return space.construct(); }); // TODO(someday): This counts tabs as single characters. Do we care? uint startLine = findLargestElementBefore(lines, startByte); uint startCol = startByte - lines[startLine]; uint endLine = findLargestElementBefore(lines, endByte); uint endCol = endByte - lines[endLine]; file->reportError( SchemaFile::SourcePos { startByte, startLine, startCol }, SchemaFile::SourcePos { endByte, endLine, endCol }, message); // We intentionally only set hadErrors true if reportError() didn't throw. parser.hadErrors = true; } bool hadErrors() override { return parser.hadErrors; } private: const SchemaParser& parser; kj::Own file; kj::Lazy> lineBreaks; // Byte offsets of the first byte in each source line. The first element is always zero. // Initialized the first time the module is loaded. }; // ======================================================================================= namespace { struct SchemaFileHash { inline size_t operator()(const SchemaFile* f) const { return f->hashCode(); } }; struct SchemaFileEq { inline bool operator()(const SchemaFile* a, const SchemaFile* b) const { return *a == *b; } }; } // namespace struct SchemaParser::DiskFileCompat { // Stuff we only create if parseDiskFile() is ever called, in order to translate that call into // KJ filesystem API calls. kj::Own ownFs; kj::Filesystem& fs; struct ImportDir { kj::String pathStr; kj::Path path; kj::Own dir; }; std::map cachedImportDirs; std::map, kj::Array> cachedImportPaths; DiskFileCompat(): ownFs(kj::newDiskFilesystem()), fs(*ownFs) {} DiskFileCompat(kj::Filesystem& fs): fs(fs) {} }; struct SchemaParser::Impl { typedef std::unordered_map< const SchemaFile*, kj::Own, SchemaFileHash, SchemaFileEq> FileMap; kj::MutexGuarded fileMap; compiler::Compiler compiler; kj::MutexGuarded> compat; }; SchemaParser::SchemaParser(): impl(kj::heap()) {} SchemaParser::~SchemaParser() noexcept(false) {} ParsedSchema SchemaParser::parseFromDirectory( const kj::ReadableDirectory& baseDir, kj::Path path, kj::ArrayPtr importPath) const { return parseFile(SchemaFile::newFromDirectory(baseDir, kj::mv(path), importPath)); } ParsedSchema SchemaParser::parseDiskFile( kj::StringPtr displayName, kj::StringPtr diskPath, kj::ArrayPtr importPath) const { auto lock = impl->compat.lockExclusive(); DiskFileCompat* compat; KJ_IF_MAYBE(c, *lock) { compat = c; } else { compat = &lock->emplace(); } auto& root = compat->fs.getRoot(); auto cwd = compat->fs.getCurrentPath(); const kj::ReadableDirectory* baseDir = &root; kj::Path path = cwd.evalNative(diskPath); kj::ArrayPtr translatedImportPath = nullptr; if (importPath.size() > 0) { auto importPathKey = std::make_pair(importPath.begin(), importPath.size()); auto& slot = compat->cachedImportPaths[importPathKey]; if (slot == nullptr) { slot = KJ_MAP(path, importPath) -> const kj::ReadableDirectory* { auto iter = compat->cachedImportDirs.find(path); if (iter != compat->cachedImportDirs.end()) { return iter->second.dir; } auto parsed = cwd.evalNative(path); kj::Own dir; KJ_IF_MAYBE(d, root.tryOpenSubdir(parsed)) { dir = kj::mv(*d); } else { // Ignore paths that don't exist. dir = kj::newInMemoryDirectory(kj::nullClock()); } const kj::ReadableDirectory* result = dir; kj::StringPtr pathRef = path; KJ_ASSERT(compat->cachedImportDirs.insert(std::make_pair(pathRef, DiskFileCompat::ImportDir { kj::str(path), kj::mv(parsed), kj::mv(dir) })).second); return result; }; } translatedImportPath = slot; // Check if `path` appears to be inside any of the import path directories. If so, adjust // to be relative to that directory rather than absolute. kj::Maybe matchedImportDir; size_t bestMatchLength = 0; for (auto importDir: importPath) { auto iter = compat->cachedImportDirs.find(importDir); KJ_ASSERT(iter != compat->cachedImportDirs.end()); if (path.startsWith(iter->second.path)) { // Looks like we're trying to load a file from inside this import path. Treat the import // path as the base directory. if (iter->second.path.size() > bestMatchLength) { bestMatchLength = iter->second.path.size(); matchedImportDir = iter->second; } } } KJ_IF_MAYBE(match, matchedImportDir) { baseDir = match->dir; path = path.slice(match->path.size(), path.size()).clone(); } } return parseFile(SchemaFile::newFromDirectory( *baseDir, kj::mv(path), translatedImportPath, kj::str(displayName))); } void SchemaParser::setDiskFilesystem(kj::Filesystem& fs) { auto lock = impl->compat.lockExclusive(); KJ_REQUIRE(*lock == nullptr, "already called parseDiskFile() or setDiskFilesystem()"); lock->emplace(fs); } ParsedSchema SchemaParser::parseFile(kj::Own&& file) const { KJ_DEFER(impl->compiler.clearWorkspace()); uint64_t id = impl->compiler.add(getModuleImpl(kj::mv(file))).getId(); impl->compiler.eagerlyCompile(id, compiler::Compiler::NODE | compiler::Compiler::CHILDREN | compiler::Compiler::DEPENDENCIES | compiler::Compiler::DEPENDENCY_DEPENDENCIES); return ParsedSchema(impl->compiler.getLoader().get(id), *this); } kj::Maybe SchemaParser::getSourceInfo(Schema schema) const { return impl->compiler.getSourceInfo(schema.getProto().getId()); } SchemaParser::ModuleImpl& SchemaParser::getModuleImpl(kj::Own&& file) const { auto lock = impl->fileMap.lockExclusive(); auto insertResult = lock->insert(std::make_pair(file.get(), kj::Own())); if (insertResult.second) { // This is a newly-inserted entry. Construct the ModuleImpl. insertResult.first->second = kj::heap(*this, kj::mv(file)); } return *insertResult.first->second; } SchemaLoader& SchemaParser::getLoader() { return impl->compiler.getLoader(); } const SchemaLoader& SchemaParser::getLoader() const { return impl->compiler.getLoader(); } kj::Maybe ParsedSchema::findNested(kj::StringPtr name) const { // TODO(someday): lookup() doesn't handle generics correctly. Use the ModuleScope/CompiledType // interface instead. We can also add an applybrand() method to ParsedSchema using those // interfaces, which would allow us to expose generics more explicitly to e.g. Python. return parser->impl->compiler.lookup(getProto().getId(), name).map( [this](uint64_t childId) { return ParsedSchema(parser->impl->compiler.getLoader().get(childId), *parser); }); } ParsedSchema ParsedSchema::getNested(kj::StringPtr nestedName) const { KJ_IF_MAYBE(nested, findNested(nestedName)) { return *nested; } else { KJ_FAIL_REQUIRE("no such nested declaration", getProto().getDisplayName(), nestedName); } } ParsedSchema::ParsedSchemaList ParsedSchema::getAllNested() const { return ParsedSchemaList(*this, getProto().getNestedNodes()); } schema::Node::SourceInfo::Reader ParsedSchema::getSourceInfo() const { return KJ_ASSERT_NONNULL(parser->getSourceInfo(*this)); } // ------------------------------------------------------------------- ParsedSchema ParsedSchema::ParsedSchemaList::operator[](uint index) const { return ParsedSchema( parent.parser->impl->compiler.getLoader().get(list[index].getId()), *parent.parser); } // ------------------------------------------------------------------- class SchemaFile::DiskSchemaFile final: public SchemaFile { public: DiskSchemaFile(const kj::ReadableDirectory& baseDir, kj::Path pathParam, kj::ArrayPtr importPath, kj::Own file, kj::Maybe displayNameOverride) : baseDir(baseDir), path(kj::mv(pathParam)), importPath(importPath), file(kj::mv(file)) { KJ_IF_MAYBE(dn, displayNameOverride) { displayName = kj::mv(*dn); displayNameOverridden = true; } else { displayName = path.toString(); displayNameOverridden = false; } } kj::StringPtr getDisplayName() const override { return displayName; } kj::Array readContent() const override { return file->mmap(0, file->stat().size).releaseAsChars(); } kj::Maybe> import(kj::StringPtr target) const override { if (target.startsWith("/")) { auto parsed = kj::Path::parse(target.slice(1)); for (auto candidate: importPath) { KJ_IF_MAYBE(newFile, candidate->tryOpenFile(parsed)) { return kj::implicitCast>(kj::heap( *candidate, kj::mv(parsed), importPath, kj::mv(*newFile), nullptr)); } } return nullptr; } else { auto parsed = path.parent().eval(target); kj::Maybe displayNameOverride; if (displayNameOverridden) { // Try to create a consistent display name override for the imported file. This is for // backwards-compatibility only -- display names are only overridden when using the // deprecated parseDiskFile() interface. kj::runCatchingExceptions([&]() { displayNameOverride = kj::Path::parse(displayName).parent().eval(target).toString(); }); } KJ_IF_MAYBE(newFile, baseDir.tryOpenFile(parsed)) { return kj::implicitCast>(kj::heap( baseDir, kj::mv(parsed), importPath, kj::mv(*newFile), kj::mv(displayNameOverride))); } else { return nullptr; } } } bool operator==(const SchemaFile& other) const override { auto& other2 = kj::downcast(other); return &baseDir == &other2.baseDir && path == other2.path; } bool operator!=(const SchemaFile& other) const override { return !operator==(other); } size_t hashCode() const override { // djb hash with xor // TODO(someday): Add hashing library to KJ. size_t result = reinterpret_cast(&baseDir); for (auto& part: path) { for (char c: part) { result = (result * 33) ^ c; } result = (result * 33) ^ '/'; } return result; } void reportError(SourcePos start, SourcePos end, kj::StringPtr message) const override { kj::getExceptionCallback().onRecoverableException(kj::Exception( kj::Exception::Type::FAILED, path.toString(), start.line, kj::heapString(message))); } private: const kj::ReadableDirectory& baseDir; kj::Path path; kj::ArrayPtr importPath; kj::Own file; kj::String displayName; bool displayNameOverridden; }; kj::Own SchemaFile::newFromDirectory( const kj::ReadableDirectory& baseDir, kj::Path path, kj::ArrayPtr importPath, kj::Maybe displayNameOverride) { return kj::heap(baseDir, kj::mv(path), importPath, baseDir.openFile(path), kj::mv(displayNameOverride)); } } // namespace capnp capnproto-c++-1.1.0/src/capnp/layout.h0000644000175000017500000014573614712011043020331 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file is NOT intended for use by clients, except in generated code. // // This file defines low-level, non-type-safe classes for traversing the Cap'n Proto memory layout // (which is also its wire format). Code generated by the Cap'n Proto compiler uses these classes, // as does other parts of the Cap'n proto library which provide a higher-level interface for // dynamic introspection. #pragma once #include #include #include "common.h" #include "blob.h" #include "endian.h" #include // work-around macro conflict with `VOID` CAPNP_BEGIN_HEADER #if (defined(__mips__) || defined(__hppa__)) && !defined(CAPNP_CANONICALIZE_NAN) #define CAPNP_CANONICALIZE_NAN 1 // Explicitly detect NaNs and canonicalize them to the quiet NaN value as would be returned by // __builtin_nan("") on systems implementing the IEEE-754 recommended (but not required) NaN // signalling/quiet differentiation (such as x86). Unfortunately, some architectures -- in // particular, MIPS -- represent quiet vs. signalling nans differently than the rest of the world. // Canonicalizing them makes output consistent (which is important!), but hurts performance // slightly. // // Note that trying to convert MIPS NaNs to standard NaNs without losing data doesn't work. // Signaling vs. quiet is indicated by a bit, with the meaning being the opposite on MIPS vs. // everyone else. It would be great if we could just flip that bit, but we can't, because if the // significand is all-zero, then the value is infinity rather than NaN. This means that on most // machines, where the bit indicates quietness, there is one more quiet NaN value than signalling // NaN value, whereas on MIPS there is one more sNaN than qNaN, and thus there is no isomorphic // mapping that properly preserves quietness. Instead of doing something hacky, we just give up // and blow away NaN payloads, because no one uses them anyway. #endif namespace capnp { class ClientHook; namespace _ { // private class PointerBuilder; class PointerReader; class StructBuilder; class StructReader; class ListBuilder; class ListReader; class OrphanBuilder; struct WirePointer; struct WireHelpers; class SegmentReader; class SegmentBuilder; class Arena; class BuilderArena; // ============================================================================= #if CAPNP_DEBUG_TYPES typedef kj::UnitRatio, BitLabel, ElementLabel> BitsPerElementTableType; #else typedef uint BitsPerElementTableType; #endif static constexpr BitsPerElementTableType BITS_PER_ELEMENT_TABLE[8] = { bounded< 0>() * BITS / ELEMENTS, bounded< 1>() * BITS / ELEMENTS, bounded< 8>() * BITS / ELEMENTS, bounded<16>() * BITS / ELEMENTS, bounded<32>() * BITS / ELEMENTS, bounded<64>() * BITS / ELEMENTS, bounded< 0>() * BITS / ELEMENTS, bounded< 0>() * BITS / ELEMENTS }; inline KJ_CONSTEXPR() BitsPerElementTableType dataBitsPerElement(ElementSize size) { return _::BITS_PER_ELEMENT_TABLE[static_cast(size)]; } inline constexpr PointersPerElementN<1> pointersPerElement(ElementSize size) { return size == ElementSize::POINTER ? PointersPerElementN<1>(ONE * POINTERS / ELEMENTS) : PointersPerElementN<1>(ZERO * POINTERS / ELEMENTS); } static constexpr BitsPerElementTableType BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[8] = { bounded< 0>() * BITS / ELEMENTS, bounded< 1>() * BITS / ELEMENTS, bounded< 8>() * BITS / ELEMENTS, bounded<16>() * BITS / ELEMENTS, bounded<32>() * BITS / ELEMENTS, bounded<64>() * BITS / ELEMENTS, bounded<64>() * BITS / ELEMENTS, bounded< 0>() * BITS / ELEMENTS }; inline KJ_CONSTEXPR() BitsPerElementTableType bitsPerElementIncludingPointers(ElementSize size) { return _::BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[static_cast(size)]; } template struct ElementSizeForByteSize; template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; }; template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; }; template <> struct ElementSizeForByteSize<4> { static constexpr ElementSize value = ElementSize::FOUR_BYTES; }; template <> struct ElementSizeForByteSize<8> { static constexpr ElementSize value = ElementSize::EIGHT_BYTES; }; template struct ElementSizeForType { static constexpr ElementSize value = // Primitive types that aren't special-cased below can be determined from sizeof(). CAPNP_KIND(T) == Kind::PRIMITIVE ? ElementSizeForByteSize::value : CAPNP_KIND(T) == Kind::ENUM ? ElementSize::TWO_BYTES : CAPNP_KIND(T) == Kind::STRUCT ? ElementSize::INLINE_COMPOSITE : // Everything else is a pointer. ElementSize::POINTER; }; // Void and bool are special. template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::VOID; }; template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::BIT; }; // Lists and blobs are pointers, not structs. template struct ElementSizeForType> { static constexpr ElementSize value = ElementSize::POINTER; }; template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::POINTER; }; template <> struct ElementSizeForType { static constexpr ElementSize value = ElementSize::POINTER; }; template inline constexpr ElementSize elementSizeForType() { return ElementSizeForType::value; } struct MessageSizeCounts { WordCountN<61, uint64_t> wordCount; // 2^64 bytes uint capCount; MessageSizeCounts& operator+=(const MessageSizeCounts& other) { // OK to truncate unchecked because this class is used to count actual stuff in memory, and // we couldn't possibly have anywhere near 2^61 words. wordCount = assumeBits<61>(wordCount + other.wordCount); capCount += other.capCount; return *this; } void addWords(WordCountN<61, uint64_t> other) { wordCount = assumeBits<61>(wordCount + other); } MessageSize asPublic() { return MessageSize { unbound(wordCount / WORDS), capCount }; } }; // ============================================================================= template union AlignedData { // Useful for declaring static constant data blobs as an array of bytes, but forcing those // bytes to be word-aligned. uint8_t bytes[wordCount * sizeof(word)]; word words[wordCount]; }; struct StructSize { StructDataWordCount data; StructPointerCount pointers; inline constexpr WordCountN<17> total() const { return data + pointers * WORDS_PER_POINTER; } StructSize() = default; inline constexpr StructSize(StructDataWordCount data, StructPointerCount pointers) : data(data), pointers(pointers) {} }; template inline constexpr StructSize structSize() { return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS, bounded(CapnpPrivate::pointerCount) * POINTERS); } template > inline constexpr StructSize minStructSizeForElement() { // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough // to hold a T. return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS, bounded(CapnpPrivate::pointerCount) * POINTERS); } template > inline constexpr StructSize minStructSizeForElement() { // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough // to hold a T. return StructSize( dataBitsPerElement(elementSizeForType()) * ELEMENTS > ZERO * BITS ? StructDataWordCount(ONE * WORDS) : StructDataWordCount(ZERO * WORDS), pointersPerElement(elementSizeForType()) * ELEMENTS); } // ------------------------------------------------------------------- // Masking of default values template struct Mask_; template struct Mask_ { typedef T Type; }; template struct Mask_ { typedef uint16_t Type; }; template <> struct Mask_ { typedef uint32_t Type; }; template <> struct Mask_ { typedef uint64_t Type; }; template struct Mask_ { // Union discriminants end up here. static_assert(sizeof(T) == 2, "Don't know how to mask this type."); typedef uint16_t Type; }; template using Mask = typename Mask_::Type; template KJ_ALWAYS_INLINE(Mask mask(T value, Mask mask)); template KJ_ALWAYS_INLINE(T unmask(Mask value, Mask mask)); template inline Mask mask(T value, Mask mask) { return static_cast >(value) ^ mask; } template <> inline uint32_t mask(float value, uint32_t mask) { #if CAPNP_CANONICALIZE_NAN if (value != value) { return 0x7fc00000u ^ mask; } #endif uint32_t i; static_assert(sizeof(i) == sizeof(value), "float is not 32 bits?"); memcpy(&i, &value, sizeof(value)); return i ^ mask; } template <> inline uint64_t mask(double value, uint64_t mask) { #if CAPNP_CANONICALIZE_NAN if (value != value) { return 0x7ff8000000000000ull ^ mask; } #endif uint64_t i; static_assert(sizeof(i) == sizeof(value), "double is not 64 bits?"); memcpy(&i, &value, sizeof(value)); return i ^ mask; } template inline T unmask(Mask value, Mask mask) { return static_cast(value ^ mask); } template <> inline float unmask(uint32_t value, uint32_t mask) { value ^= mask; float result; static_assert(sizeof(result) == sizeof(value), "float is not 32 bits?"); memcpy(&result, &value, sizeof(value)); return result; } template <> inline double unmask(uint64_t value, uint64_t mask) { value ^= mask; double result; static_assert(sizeof(result) == sizeof(value), "double is not 64 bits?"); memcpy(&result, &value, sizeof(value)); return result; } // ------------------------------------------------------------------- class CapTableReader { public: virtual kj::Maybe> extractCap(uint index) = 0; // Extract the capability at the given index. If the index is invalid, returns null. }; class CapTableBuilder: public CapTableReader { public: virtual uint injectCap(kj::Own&& cap) = 0; // Add the capability to the message and return its index. If the same ClientHook is injected // twice, this may return the same index both times, but in this case dropCap() needs to be // called an equal number of times to actually remove the cap. virtual void dropCap(uint index) = 0; // Remove a capability injected earlier. Called when the pointer is overwritten or zero'd out. }; // ------------------------------------------------------------------- class PointerBuilder: public kj::DisallowConstCopy { // Represents a single pointer, usually embedded in a struct or a list. public: inline PointerBuilder(): segment(nullptr), capTable(nullptr), pointer(nullptr) {} static inline PointerBuilder getRoot( SegmentBuilder* segment, CapTableBuilder* capTable, word* location); // Get a PointerBuilder representing a message root located in the given segment at the given // location. inline bool isNull() { return getPointerType() == PointerType::NULL_; } PointerType getPointerType() const; StructBuilder getStruct(StructSize size, const word* defaultValue); ListBuilder getList(ElementSize elementSize, const word* defaultValue); ListBuilder getStructList(StructSize elementSize, const word* defaultValue); ListBuilder getListAnySize(const word* defaultValue); template typename T::Builder getBlob( const void* defaultValue, ByteCount defaultSize); #if !CAPNP_LITE kj::Own getCapability(); #endif // !CAPNP_LITE // Get methods: Get the value. If it is null, initialize it to a copy of the default value. // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a // simple byte array for blobs. StructBuilder initStruct(StructSize size); ListBuilder initList(ElementSize elementSize, ElementCount elementCount); ListBuilder initStructList(ElementCount elementCount, StructSize size); template typename T::Builder initBlob(ByteCount size); // Init methods: Initialize the pointer to a newly-allocated object, discarding the existing // object. void setStruct(const StructReader& value, bool canonical = false); void setList(const ListReader& value, bool canonical = false); template void setBlob(typename T::Reader value); #if !CAPNP_LITE void setCapability(kj::Own&& cap); #endif // !CAPNP_LITE // Set methods: Initialize the pointer to a newly-allocated copy of the given value, discarding // the existing object. void adopt(OrphanBuilder&& orphan); // Set the pointer to point at the given orphaned value. OrphanBuilder disown(); // Set the pointer to null and return its previous value as an orphan. void clear(); // Clear the pointer to null, discarding its previous value. void transferFrom(PointerBuilder other); // Equivalent to `adopt(other.disown())`. void copyFrom(PointerReader other, bool canonical = false); // Equivalent to `set(other.get())`. // If you set the canonical flag, it will attempt to lay the target out // canonically, provided enough space is available. PointerReader asReader() const; BuilderArena* getArena() const; // Get the arena containing this pointer. CapTableBuilder* getCapTable(); // Gets the capability context in which this object is operating. PointerBuilder imbue(CapTableBuilder* capTable); // Return a copy of this builder except using the given capability context. private: SegmentBuilder* segment; // Memory segment in which the pointer resides. CapTableBuilder* capTable; // Table of capability indexes. WirePointer* pointer; // Pointer to the pointer. inline PointerBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* pointer) : segment(segment), capTable(capTable), pointer(pointer) {} friend class StructBuilder; friend class ListBuilder; friend class OrphanBuilder; }; class PointerReader { public: inline PointerReader() : segment(nullptr), capTable(nullptr), pointer(nullptr), nestingLimit(0x7fffffff) {} static PointerReader getRoot(SegmentReader* segment, CapTableReader* capTable, const word* location, int nestingLimit); // Get a PointerReader representing a message root located in the given segment at the given // location. static inline PointerReader getRootUnchecked(const word* location); // Get a PointerReader for an unchecked message. MessageSizeCounts targetSize() const; // Return the total size of the target object and everything to which it points. Does not count // far pointer overhead. This is useful for deciding how much space is needed to copy the object // into a flat array. However, the caller is advised NOT to treat this value as secure. Instead, // use the result as a hint for allocating the first segment, do the copy, and then throw an // exception if it overruns. inline bool isNull() const { return getPointerType() == PointerType::NULL_; } PointerType getPointerType() const; StructReader getStruct(const word* defaultValue) const; ListReader getList(ElementSize expectedElementSize, const word* defaultValue) const; ListReader getListAnySize(const word* defaultValue) const; template typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const; #if !CAPNP_LITE kj::Own getCapability() const; #endif // !CAPNP_LITE // Get methods: Get the value. If it is null, return the default value instead. // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a // simple byte array for blobs. const word* getUnchecked() const; // If this is an unchecked message, get a word* pointing at the location of the pointer. This // word* can actually be passed to readUnchecked() to read the designated sub-object later. If // this isn't an unchecked message, throws an exception. kj::Maybe getArena() const; // Get the arena containing this pointer. CapTableReader* getCapTable(); // Gets the capability context in which this object is operating. PointerReader imbue(CapTableReader* capTable) const; // Return a copy of this reader except using the given capability context. bool isCanonical(const word **readHead); // Validate this pointer's canonicity, subject to the conditions: // * All data to the left of readHead has been read thus far (for pointer // ordering) // * All pointers in preorder have already been checked // * This pointer is in the first and only segment of the message private: SegmentReader* segment; // Memory segment in which the pointer resides. CapTableReader* capTable; // Table of capability indexes. const WirePointer* pointer; // Pointer to the pointer. null = treat as null pointer. int nestingLimit; // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. // Once this reaches zero, further pointers will be pruned. inline PointerReader(SegmentReader* segment, CapTableReader* capTable, const WirePointer* pointer, int nestingLimit) : segment(segment), capTable(capTable), pointer(pointer), nestingLimit(nestingLimit) {} friend class StructReader; friend class ListReader; friend class PointerBuilder; friend class OrphanBuilder; }; // ------------------------------------------------------------------- class StructBuilder: public kj::DisallowConstCopy { public: inline StructBuilder(): segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr) {} inline word* getLocation() { return reinterpret_cast(data); } // Get the object's location. Only valid for independently-allocated objects (i.e. not list // elements). inline StructDataBitCount getDataSectionSize() const { return dataSize; } inline StructPointerCount getPointerSectionSize() const { return pointerCount; } inline kj::ArrayPtr getDataSectionAsBlob(); inline _::ListBuilder getPointerSectionAsList(); template KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset)); // Return true if the field is set to something other than its default value. template KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset)); // Gets the data field value of the given type at the given offset. The offset is measured in // multiples of the field size, determined by the type. template KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask mask)); // Like getDataField() but applies the given XOR mask to the data on load. Used for reading // fields with non-zero default values. template KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer value)); // Sets the data field value at the given offset. template KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer value, Mask mask)); // Like setDataField() but applies the given XOR mask before storing. Used for writing fields // with non-zero default values. KJ_ALWAYS_INLINE(PointerBuilder getPointerField(StructPointerOffset ptrIndex)); // Get a builder for a pointer field given the index within the pointer section. void clearAll(); // Clear all pointers and data. void transferContentFrom(StructBuilder other); // Adopt all pointers from `other`, and also copy all data. If `other`'s sections are larger // than this, the extra data is not transferred, meaning there is a risk of data loss when // transferring from messages built with future versions of the protocol. void copyContentFrom(StructReader other); // Copy content from `other`. If `other`'s sections are larger than this, the extra data is not // copied, meaning there is a risk of data loss when copying from messages built with future // versions of the protocol. StructReader asReader() const; // Gets a StructReader pointing at the same memory. BuilderArena* getArena(); // Gets the arena in which this object is allocated. CapTableBuilder* getCapTable(); // Gets the capability context in which this object is operating. StructBuilder imbue(CapTableBuilder* capTable); // Return a copy of this builder except using the given capability context. private: SegmentBuilder* segment; // Memory segment in which the struct resides. CapTableBuilder* capTable; // Table of capability indexes. void* data; // Pointer to the encoded data. WirePointer* pointers; // Pointer to the encoded pointers. StructDataBitCount dataSize; // Size of data section. We use a bit count rather than a word count to more easily handle the // case of struct lists encoded with less than a word per element. StructPointerCount pointerCount; // Size of the pointer section. inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* data, WirePointer* pointers, StructDataBitCount dataSize, StructPointerCount pointerCount) : segment(segment), capTable(capTable), data(data), pointers(pointers), dataSize(dataSize), pointerCount(pointerCount) {} friend class ListBuilder; friend struct WireHelpers; friend class OrphanBuilder; }; class StructReader { public: inline StructReader() : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr), dataSize(ZERO * BITS), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} inline StructReader(kj::ArrayPtr data) : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr), dataSize(assumeBits(data.size()) * WORDS * BITS_PER_WORD), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {} const void* getLocation() const { return data; } inline StructDataBitCount getDataSectionSize() const { return dataSize; } inline StructPointerCount getPointerSectionSize() const { return pointerCount; } inline kj::ArrayPtr getDataSectionAsBlob() const; inline _::ListReader getPointerSectionAsList() const; kj::Array canonicalize(); template KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset) const); // Return true if the field is set to something other than its default value. template KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset) const); // Get the data field value of the given type at the given offset. The offset is measured in // multiples of the field size, determined by the type. Returns zero if the offset is past the // end of the struct's data section. template KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask mask) const); // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading // fields with non-zero default values. KJ_ALWAYS_INLINE(PointerReader getPointerField(StructPointerOffset ptrIndex) const); // Get a reader for a pointer field given the index within the pointer section. If the index // is out-of-bounds, returns a null pointer. MessageSizeCounts totalSize() const; // Return the total size of the struct and everything to which it points. Does not count far // pointer overhead. This is useful for deciding how much space is needed to copy the struct // into a flat array. CapTableReader* getCapTable(); // Gets the capability context in which this object is operating. StructReader imbue(CapTableReader* capTable) const; // Return a copy of this reader except using the given capability context. bool isCanonical(const word **readHead, const word **ptrHead, bool *dataTrunc, bool *ptrTrunc); // Validate this pointer's canonicity, subject to the conditions: // * All data to the left of readHead has been read thus far (for pointer // ordering) // * All pointers in preorder have already been checked // * This pointer is in the first and only segment of the message // // If this function returns false, the struct is non-canonical. If it // returns true, then: // * If it is a composite in a list, it is canonical if at least one struct // in the list outputs dataTrunc = 1, and at least one outputs ptrTrunc = 1 // * If it is derived from a struct pointer, it is canonical if // dataTrunc = 1 AND ptrTrunc = 1 private: SegmentReader* segment; // Memory segment in which the struct resides. CapTableReader* capTable; // Table of capability indexes. const void* data; const WirePointer* pointers; StructDataBitCount dataSize; // Size of data section. We use a bit count rather than a word count to more easily handle the // case of struct lists encoded with less than a word per element. StructPointerCount pointerCount; // Size of the pointer section. int nestingLimit; // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. // Once this reaches zero, further pointers will be pruned. // TODO(perf): Limit to 16 bits for better packing? inline StructReader(SegmentReader* segment, CapTableReader* capTable, const void* data, const WirePointer* pointers, StructDataBitCount dataSize, StructPointerCount pointerCount, int nestingLimit) : segment(segment), capTable(capTable), data(data), pointers(pointers), dataSize(dataSize), pointerCount(pointerCount), nestingLimit(nestingLimit) {} friend class ListReader; friend class StructBuilder; friend struct WireHelpers; }; // ------------------------------------------------------------------- class ListBuilder: public kj::DisallowConstCopy { public: inline explicit ListBuilder(ElementSize elementSize) : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), structPointerCount(ZERO * POINTERS), elementSize(elementSize) {} inline word* getLocation() { // Get the object's location. if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) { return reinterpret_cast(ptr) - POINTER_SIZE_IN_WORDS; } else { return reinterpret_cast(ptr); } } inline ElementSize getElementSize() const { return elementSize; } inline ListElementCount size() const; // The number of elements in the list. Text::Builder asText(); Data::Builder asData(); // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. template KJ_ALWAYS_INLINE(T getDataElement(ElementCount index)); // Get the element of the given type at the given index. template KJ_ALWAYS_INLINE(void setDataElement(ElementCount index, kj::NoInfer value)); // Set the element at the given index. KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index)); StructBuilder getStructElement(ElementCount index); ListReader asReader() const; // Get a ListReader pointing at the same memory. BuilderArena* getArena(); // Gets the arena in which this object is allocated. CapTableBuilder* getCapTable(); // Gets the capability context in which this object is operating. ListBuilder imbue(CapTableBuilder* capTable); // Return a copy of this builder except using the given capability context. private: SegmentBuilder* segment; // Memory segment in which the list resides. CapTableBuilder* capTable; // Table of capability indexes. byte* ptr; // Pointer to list content. ListElementCount elementCount; // Number of elements in the list. BitsPerElementN<23> step; // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 128 bits. StructDataBitCount structDataSize; StructPointerCount structPointerCount; // The struct properties to use when interpreting the elements as structs. All lists can be // interpreted as struct lists, so these are always filled in. ElementSize elementSize; // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE // from other types when the overall size is exactly zero or one words. inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr, BitsPerElementN<23> step, ListElementCount size, StructDataBitCount structDataSize, StructPointerCount structPointerCount, ElementSize elementSize) : segment(segment), capTable(capTable), ptr(reinterpret_cast(ptr)), elementCount(size), step(step), structDataSize(structDataSize), structPointerCount(structPointerCount), elementSize(elementSize) {} friend class StructBuilder; friend struct WireHelpers; friend class OrphanBuilder; }; class ListReader { public: inline explicit ListReader(ElementSize elementSize) : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS), step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS), structPointerCount(ZERO * POINTERS), elementSize(elementSize), nestingLimit(0x7fffffff) {} inline ListElementCount size() const; // The number of elements in the list. inline ElementSize getElementSize() const { return elementSize; } Text::Reader asText(); Data::Reader asData(); // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. kj::ArrayPtr asRawBytes() const; template KJ_ALWAYS_INLINE(T getDataElement(ElementCount index) const); // Get the element of the given type at the given index. KJ_ALWAYS_INLINE(PointerReader getPointerElement(ElementCount index) const); StructReader getStructElement(ElementCount index) const; MessageSizeCounts totalSize() const; // Like StructReader::totalSize(). Note that for struct lists, the size includes the list tag. CapTableReader* getCapTable(); // Gets the capability context in which this object is operating. ListReader imbue(CapTableReader* capTable) const; // Return a copy of this reader except using the given capability context. bool isCanonical(const word **readHead, const WirePointer* ref); // Validate this pointer's canonicity, subject to the conditions: // * All data to the left of readHead has been read thus far (for pointer // ordering) // * All pointers in preorder have already been checked // * This pointer is in the first and only segment of the message private: SegmentReader* segment; // Memory segment in which the list resides. CapTableReader* capTable; // Table of capability indexes. const byte* ptr; // Pointer to list content. ListElementCount elementCount; // Number of elements in the list. BitsPerElementN<23> step; // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 2 bits. StructDataBitCount structDataSize; StructPointerCount structPointerCount; // The struct properties to use when interpreting the elements as structs. All lists can be // interpreted as struct lists, so these are always filled in. ElementSize elementSize; // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE // from other types when the overall size is exactly zero or one words. int nestingLimit; // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. // Once this reaches zero, further pointers will be pruned. inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr, ListElementCount elementCount, BitsPerElementN<23> step, StructDataBitCount structDataSize, StructPointerCount structPointerCount, ElementSize elementSize, int nestingLimit) : segment(segment), capTable(capTable), ptr(reinterpret_cast(ptr)), elementCount(elementCount), step(step), structDataSize(structDataSize), structPointerCount(structPointerCount), elementSize(elementSize), nestingLimit(nestingLimit) {} friend class StructReader; friend class ListBuilder; friend struct WireHelpers; friend class OrphanBuilder; }; // ------------------------------------------------------------------- class OrphanBuilder { public: inline OrphanBuilder(): segment(nullptr), capTable(nullptr), location(nullptr) { memset(&tag, 0, sizeof(tag)); } OrphanBuilder(const OrphanBuilder& other) = delete; inline OrphanBuilder(OrphanBuilder&& other) noexcept; inline ~OrphanBuilder() noexcept(false); static OrphanBuilder initStruct(BuilderArena* arena, CapTableBuilder* capTable, StructSize size); static OrphanBuilder initList(BuilderArena* arena, CapTableBuilder* capTable, ElementCount elementCount, ElementSize elementSize); static OrphanBuilder initStructList(BuilderArena* arena, CapTableBuilder* capTable, ElementCount elementCount, StructSize elementSize); static OrphanBuilder initText(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size); static OrphanBuilder initData(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size); static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, StructReader copyFrom); static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, ListReader copyFrom); static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, PointerReader copyFrom); static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Text::Reader copyFrom); static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Data::Reader copyFrom); #if !CAPNP_LITE static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, kj::Own copyFrom); #endif // !CAPNP_LITE static OrphanBuilder concat(BuilderArena* arena, CapTableBuilder* capTable, ElementSize expectedElementSize, StructSize expectedStructSize, kj::ArrayPtr lists); static OrphanBuilder referenceExternalData(BuilderArena* arena, Data::Reader data); OrphanBuilder& operator=(const OrphanBuilder& other) = delete; inline OrphanBuilder& operator=(OrphanBuilder&& other); inline bool operator==(decltype(nullptr)) const { return location == nullptr; } inline bool operator!=(decltype(nullptr)) const { return location != nullptr; } StructBuilder asStruct(StructSize size); // Interpret as a struct, or throw an exception if not a struct. ListBuilder asList(ElementSize elementSize); // Interpret as a list, or throw an exception if not a list. elementSize cannot be // INLINE_COMPOSITE -- use asStructList() instead. ListBuilder asStructList(StructSize elementSize); // Interpret as a struct list, or throw an exception if not a list. ListBuilder asListAnySize(); // For AnyList. Text::Builder asText(); Data::Builder asData(); // Interpret as a blob, or throw an exception if not a blob. StructReader asStructReader(StructSize size) const; ListReader asListReader(ElementSize elementSize) const; ListReader asListReaderAnySize() const; #if !CAPNP_LITE kj::Own asCapability() const; #endif // !CAPNP_LITE Text::Reader asTextReader() const; Data::Reader asDataReader() const; bool truncate(ElementCount size, bool isText) KJ_WARN_UNUSED_RESULT; // Resize the orphan list to the given size. Returns false if the list is currently empty but // the requested size is non-zero, in which case the caller will need to allocate a new list. void truncate(ElementCount size, ElementSize elementSize); void truncate(ElementCount size, StructSize elementSize); void truncateText(ElementCount size); // Versions of truncate() that know how to allocate a new list if needed. private: static_assert(ONE * POINTERS * WORDS_PER_POINTER == ONE * WORDS, "This struct assumes a pointer is one word."); word tag; // Contains an encoded WirePointer representing this object. WirePointer is defined in // layout.c++, but fits in a word. // // This may be a FAR pointer. Even in that case, `location` points to the eventual destination // of that far pointer. The reason we keep the far pointer around rather than just making `tag` // represent the final destination is because if the eventual adopter of the pointer is not in // the target's segment then it may be useful to reuse the far pointer landing pad. // // If `tag` is not a far pointer, its offset is garbage; only `location` points to the actual // target. SegmentBuilder* segment; // Segment in which the object resides. CapTableBuilder* capTable; // Table of capability indexes. word* location; // Pointer to the object, or nullptr if the pointer is null. For capabilities, we make this // 0x1 just so that it is non-null for operator==, but it is never used. inline OrphanBuilder(const void* tagPtr, SegmentBuilder* segment, CapTableBuilder* capTable, word* location) : segment(segment), capTable(capTable), location(location) { memcpy(&tag, tagPtr, sizeof(tag)); } inline WirePointer* tagAsPtr() { return reinterpret_cast(&tag); } inline const WirePointer* tagAsPtr() const { return reinterpret_cast(&tag); } void euthanize(); // Erase the target object, zeroing it out and possibly reclaiming the memory. Called when // the OrphanBuilder is being destroyed or overwritten and it is non-null. friend struct WireHelpers; }; // ======================================================================================= // Internal implementation details... // These are defined in the source file. template <> typename Text::Builder PointerBuilder::initBlob(ByteCount size); template <> void PointerBuilder::setBlob(typename Text::Reader value); template <> typename Text::Builder PointerBuilder::getBlob( const void* defaultValue, ByteCount defaultSize); template <> typename Text::Reader PointerReader::getBlob( const void* defaultValue, ByteCount defaultSize) const; template <> typename Data::Builder PointerBuilder::initBlob(ByteCount size); template <> void PointerBuilder::setBlob(typename Data::Reader value); template <> typename Data::Builder PointerBuilder::getBlob( const void* defaultValue, ByteCount defaultSize); template <> typename Data::Reader PointerReader::getBlob( const void* defaultValue, ByteCount defaultSize) const; inline PointerBuilder PointerBuilder::getRoot( SegmentBuilder* segment, CapTableBuilder* capTable, word* location) { return PointerBuilder(segment, capTable, reinterpret_cast(location)); } inline PointerReader PointerReader::getRootUnchecked(const word* location) { return PointerReader(nullptr, nullptr, reinterpret_cast(location), 0x7fffffff); } // ------------------------------------------------------------------- inline kj::ArrayPtr StructBuilder::getDataSectionAsBlob() { return kj::ArrayPtr(reinterpret_cast(data), unbound(dataSize / BITS_PER_BYTE / BYTES)); } inline _::ListBuilder StructBuilder::getPointerSectionAsList() { return _::ListBuilder(segment, capTable, pointers, ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, pointerCount * (ONE * ELEMENTS / POINTERS), ZERO * BITS, ONE * POINTERS, ElementSize::POINTER); } template inline bool StructBuilder::hasDataField(StructDataOffset offset) { return getDataField>(offset) != 0; } template <> inline bool StructBuilder::hasDataField(StructDataOffset offset) { return false; } template inline T StructBuilder::getDataField(StructDataOffset offset) { return reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].get(); } template <> inline bool StructBuilder::getDataField(StructDataOffset offset) { BitCount32 boffset = offset * (ONE * BITS / ELEMENTS); byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; return (*reinterpret_cast(b) & unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; } template <> inline Void StructBuilder::getDataField(StructDataOffset offset) { return VOID; } template inline T StructBuilder::getDataField(StructDataOffset offset, Mask mask) { return unmask(getDataField >(offset), mask); } template inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer value) { reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].set(value); } #if CAPNP_CANONICALIZE_NAN // Use mask() on floats and doubles to make sure we canonicalize NaNs. template <> inline void StructBuilder::setDataField(StructDataOffset offset, float value) { setDataField(offset, mask(value, 0)); } template <> inline void StructBuilder::setDataField(StructDataOffset offset, double value) { setDataField(offset, mask(value, 0)); } #endif template <> inline void StructBuilder::setDataField(StructDataOffset offset, bool value) { auto boffset = offset * (ONE * BITS / ELEMENTS); byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; uint bitnum = unboundMaxBits<3>(boffset % BITS_PER_BYTE / BITS); *reinterpret_cast(b) = (*reinterpret_cast(b) & ~(1 << bitnum)) | (static_cast(value) << bitnum); } template <> inline void StructBuilder::setDataField(StructDataOffset offset, Void value) {} template inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer value, Mask m) { setDataField >(offset, mask(value, m)); } inline PointerBuilder StructBuilder::getPointerField(StructPointerOffset ptrIndex) { // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). return PointerBuilder(segment, capTable, reinterpret_cast( reinterpret_cast(pointers) + ptrIndex * WORDS_PER_POINTER)); } // ------------------------------------------------------------------- inline kj::ArrayPtr StructReader::getDataSectionAsBlob() const { return kj::ArrayPtr(reinterpret_cast(data), unbound(dataSize / BITS_PER_BYTE / BYTES)); } inline _::ListReader StructReader::getPointerSectionAsList() const { return _::ListReader(segment, capTable, pointers, pointerCount * (ONE * ELEMENTS / POINTERS), ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, ZERO * BITS, ONE * POINTERS, ElementSize::POINTER, nestingLimit); } template inline bool StructReader::hasDataField(StructDataOffset offset) const { return getDataField>(offset) != 0; } template <> inline bool StructReader::hasDataField(StructDataOffset offset) const { return false; } template inline T StructReader::getDataField(StructDataOffset offset) const { if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement() <= dataSize) { return reinterpret_cast*>(data)[unbound(offset / ELEMENTS)].get(); } else { return static_cast(0); } } template <> inline bool StructReader::getDataField(StructDataOffset offset) const { auto boffset = offset * (ONE * BITS / ELEMENTS); if (boffset < dataSize) { const byte* b = reinterpret_cast(data) + boffset / BITS_PER_BYTE; return (*reinterpret_cast(b) & unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0; } else { return false; } } template <> inline Void StructReader::getDataField(StructDataOffset offset) const { return VOID; } template T StructReader::getDataField(StructDataOffset offset, Mask mask) const { return unmask(getDataField >(offset), mask); } inline PointerReader StructReader::getPointerField(StructPointerOffset ptrIndex) const { if (ptrIndex < pointerCount) { // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). return PointerReader(segment, capTable, reinterpret_cast( reinterpret_cast(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit); } else{ return PointerReader(); } } // ------------------------------------------------------------------- inline ListElementCount ListBuilder::size() const { return elementCount; } template inline T ListBuilder::getDataElement(ElementCount index) { return reinterpret_cast*>( ptr + upgradeBound(index) * step / BITS_PER_BYTE)->get(); // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and // the various non-inline methods that look up pointers. // Also if using this, consider changing ptr back to void* instead of byte*. // return reinterpret_cast*>(ptr)[ // index / ELEMENTS * (step / capnp::bitsPerElement())].get(); } template <> inline bool ListBuilder::getDataElement(ElementCount index) { // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. auto bindex = index * (ONE * BITS / ELEMENTS); byte* b = ptr + bindex / BITS_PER_BYTE; return (*reinterpret_cast(b) & unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; } template <> inline Void ListBuilder::getDataElement(ElementCount index) { return VOID; } template inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer value) { reinterpret_cast*>( ptr + upgradeBound(index) * step / BITS_PER_BYTE)->set(value); } #if CAPNP_CANONICALIZE_NAN // Use mask() on floats and doubles to make sure we canonicalize NaNs. template <> inline void ListBuilder::setDataElement(ElementCount index, float value) { setDataElement(index, mask(value, 0)); } template <> inline void ListBuilder::setDataElement(ElementCount index, double value) { setDataElement(index, mask(value, 0)); } #endif template <> inline void ListBuilder::setDataElement(ElementCount index, bool value) { // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists. auto bindex = index * (ONE * BITS / ELEMENTS); byte* b = ptr + bindex / BITS_PER_BYTE; auto bitnum = bindex % BITS_PER_BYTE / BITS; *reinterpret_cast(b) = (*reinterpret_cast(b) & ~(1 << unbound(bitnum))) | (static_cast(value) << unbound(bitnum)); } template <> inline void ListBuilder::setDataElement(ElementCount index, Void value) {} inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) { return PointerBuilder(segment, capTable, reinterpret_cast(ptr + upgradeBound(index) * step / BITS_PER_BYTE)); } // ------------------------------------------------------------------- inline ListElementCount ListReader::size() const { return elementCount; } template inline T ListReader::getDataElement(ElementCount index) const { return reinterpret_cast*>( ptr + upgradeBound(index) * step / BITS_PER_BYTE)->get(); } template <> inline bool ListReader::getDataElement(ElementCount index) const { // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. auto bindex = index * (ONE * BITS / ELEMENTS); const byte* b = ptr + bindex / BITS_PER_BYTE; return (*reinterpret_cast(b) & unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0; } template <> inline Void ListReader::getDataElement(ElementCount index) const { return VOID; } inline PointerReader ListReader::getPointerElement(ElementCount index) const { // If the list elements have data sections we need to skip those. Note that for pointers to be // present at all (which already must be true if we get here), then `structDataSize` must be a // whole number of words, so we don't have to worry about unaligned reads here. auto offset = structDataSize / BITS_PER_BYTE; return PointerReader(segment, capTable, reinterpret_cast( ptr + offset + upgradeBound(index) * step / BITS_PER_BYTE), nestingLimit); } // ------------------------------------------------------------------- inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept : segment(other.segment), capTable(other.capTable), location(other.location) { memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules. other.segment = nullptr; other.location = nullptr; } inline OrphanBuilder::~OrphanBuilder() noexcept(false) { if (segment != nullptr) euthanize(); } inline OrphanBuilder& OrphanBuilder::operator=(OrphanBuilder&& other) { // With normal smart pointers, it's important to handle the case where the incoming pointer // is actually transitively owned by this one. In this case, euthanize() would destroy `other` // before we copied it. This isn't possible in the case of `OrphanBuilder` because it only // owns message objects, and `other` is not itself a message object, therefore cannot possibly // be transitively owned by `this`. if (segment != nullptr) euthanize(); segment = other.segment; capTable = other.capTable; location = other.location; memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules. other.segment = nullptr; other.location = nullptr; return *this; } } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compat/0000755000175000017500000000000014731562205020122 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/capnp/compat/websocket-rpc.c++0000644000175000017500000001240314712011043023150 0ustar00kentonkenton00000000000000// Copyright (c) 2021 Ian Denhardt and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include #include #include namespace capnp { WebSocketMessageStream::WebSocketMessageStream(kj::WebSocket& socket) : socket(socket) {}; kj::Promise> WebSocketMessageStream::tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options, kj::ArrayPtr scratchSpace) { return socket.receive(options.traversalLimitInWords * sizeof(word)) .then([options](auto msg) -> kj::Promise> { KJ_SWITCH_ONEOF(msg) { KJ_CASE_ONEOF(closeMsg, kj::WebSocket::Close) { return kj::Maybe(); } KJ_CASE_ONEOF(str, kj::String) { KJ_FAIL_REQUIRE( "Unexpected websocket text message; expected only binary messages."); break; } KJ_CASE_ONEOF(bytes, kj::Array) { kj::Own reader; size_t sizeInWords = bytes.size() / sizeof(word); if (reinterpret_cast(bytes.begin()) % alignof(word) == 0) { reader = kj::heap( kj::arrayPtr( reinterpret_cast(bytes.begin()), sizeInWords ), options).attach(kj::mv(bytes)); } else { // The array is misaligned, so we need to copy it. auto words = kj::heapArray(sizeInWords); // Note: can't just use bytes.size(), since the the target buffer may // be shorter due to integer division. memcpy(words.begin(), bytes.begin(), sizeInWords * sizeof(word)); reader = kj::heap( kj::arrayPtr(words.begin(), sizeInWords), options).attach(kj::mv(words)); } return kj::Maybe(MessageReaderAndFds { kj::mv(reader), nullptr }); } } KJ_UNREACHABLE; }); } kj::Promise WebSocketMessageStream::writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) { // TODO(perf): Right now the WebSocket interface only supports send() for // contiguous arrays, so we need to copy the whole message into a new buffer // in order to send it, whereas ideally we could just write each segment // (and the segment table) in sequence. Perhaps we should extend the WebSocket // interface to be able to send an ArrayPtr> as one binary // message, and then use that to avoid an extra copy here. auto stream = kj::heap( computeSerializedSizeInWords(segments) * sizeof(word)); capnp::writeMessage(*stream, segments); auto arrayPtr = stream->getArray(); return socket.send(arrayPtr).attach(kj::mv(stream)); } kj::Promise WebSocketMessageStream::writeMessages( kj::ArrayPtr>> messages) { // TODO(perf): Extend WebSocket interface with a way to write multiple messages at once. if(messages.size() == 0) { return kj::READY_NOW; } return writeMessage(nullptr, messages[0]) .then([this, messages = messages.slice(1, messages.size())]() mutable -> kj::Promise { return writeMessages(messages); }); } kj::Maybe WebSocketMessageStream::getSendBufferSize() { return nullptr; } kj::Promise WebSocketMessageStream::end() { return socket.close( 1005, // most generic code, indicates "No Status Received." // Since the MessageStream API doesn't tell us why // we're closing the connection, this is the best // we can do. This is consistent with what browser // implementations do if no status is provided, see: // // * https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close // * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent "Capnp connection closed" // Similarly not much information to go on here, // but this at least lets us trace this back to // capnp. ); }; }; capnproto-c++-1.1.0/src/capnp/compat/websocket-rpc.h0000644000175000017500000000432714527152321023046 0ustar00kentonkenton00000000000000// Copyright (c) 2021 Ian Denhardt and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include CAPNP_BEGIN_HEADER namespace capnp { class WebSocketMessageStream final : public MessageStream { // An implementation of MessageStream that sends messages over a websocket. // // Each capnproto message is sent in a single binary websocket frame. public: WebSocketMessageStream(kj::WebSocket& socket); // Implements MessageStream kj::Promise> tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) override; kj::Promise writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) override KJ_WARN_UNUSED_RESULT; kj::Promise writeMessages( kj::ArrayPtr>> messages) override KJ_WARN_UNUSED_RESULT; kj::Maybe getSendBufferSize() override; kj::Promise end() override; private: kj::WebSocket& socket; }; } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compat/json.capnp.h0000644000175000017500000014012414731562162022350 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: json.capnp #pragma once #include #include #if !CAPNP_LITE #include #endif // !CAPNP_LITE #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(a3fa7845f919dd83); CAPNP_DECLARE_SCHEMA(e31026e735d69ddf); CAPNP_DECLARE_SCHEMA(a0d9f6eca1c93d48); CAPNP_DECLARE_SCHEMA(fa5b1fd61c2e7c3d); CAPNP_DECLARE_SCHEMA(82d3e852af0336bf); CAPNP_DECLARE_SCHEMA(c4df13257bc2ea61); CAPNP_DECLARE_SCHEMA(cfa794e8d19a0162); CAPNP_DECLARE_SCHEMA(c2f8c20c293e5319); CAPNP_DECLARE_SCHEMA(d7d879450a253e4b); CAPNP_DECLARE_SCHEMA(f061e22f0ae5c7b5); CAPNP_DECLARE_SCHEMA(a0a054dea32fd98c); } // namespace schemas } // namespace capnp namespace capnp { namespace json { struct Value { Value() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NULL_, BOOLEAN, NUMBER, STRING, ARRAY, OBJECT, CALL, RAW, }; struct Field; struct Call; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(a3fa7845f919dd83, 2, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Value::Field { Field() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e31026e735d69ddf, 0, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Value::Call { Call() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(a0d9f6eca1c93d48, 0, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct FlattenOptions { FlattenOptions() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c4df13257bc2ea61, 0, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct DiscriminatorOptions { DiscriminatorOptions() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(c2f8c20c293e5319, 0, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class Value::Reader { public: typedef Value Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNull() const; inline ::capnp::Void getNull() const; inline bool isBoolean() const; inline bool getBoolean() const; inline bool isNumber() const; inline double getNumber() const; inline bool isString() const; inline bool hasString() const; inline ::capnp::Text::Reader getString() const; inline bool isArray() const; inline bool hasArray() const; inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader getArray() const; inline bool isObject() const; inline bool hasObject() const; inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Reader getObject() const; inline bool isCall() const; inline bool hasCall() const; inline ::capnp::json::Value::Call::Reader getCall() const; inline bool isRaw() const; inline bool hasRaw() const; inline ::capnp::Text::Reader getRaw() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Value::Builder { public: typedef Value Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNull(); inline ::capnp::Void getNull(); inline void setNull( ::capnp::Void value = ::capnp::VOID); inline bool isBoolean(); inline bool getBoolean(); inline void setBoolean(bool value); inline bool isNumber(); inline double getNumber(); inline void setNumber(double value); inline bool isString(); inline bool hasString(); inline ::capnp::Text::Builder getString(); inline void setString( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initString(unsigned int size); inline void adoptString(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownString(); inline bool isArray(); inline bool hasArray(); inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder getArray(); inline void setArray( ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder initArray(unsigned int size); inline void adoptArray(::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>> disownArray(); inline bool isObject(); inline bool hasObject(); inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Builder getObject(); inline void setObject( ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Builder initObject(unsigned int size); inline void adoptObject(::capnp::Orphan< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>> disownObject(); inline bool isCall(); inline bool hasCall(); inline ::capnp::json::Value::Call::Builder getCall(); inline void setCall( ::capnp::json::Value::Call::Reader value); inline ::capnp::json::Value::Call::Builder initCall(); inline void adoptCall(::capnp::Orphan< ::capnp::json::Value::Call>&& value); inline ::capnp::Orphan< ::capnp::json::Value::Call> disownCall(); inline bool isRaw(); inline bool hasRaw(); inline ::capnp::Text::Builder getRaw(); inline void setRaw( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initRaw(unsigned int size); inline void adoptRaw(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownRaw(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Value::Pipeline { public: typedef Value Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Value::Field::Reader { public: typedef Field Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline bool hasValue() const; inline ::capnp::json::Value::Reader getValue() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Value::Field::Builder { public: typedef Field Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline bool hasValue(); inline ::capnp::json::Value::Builder getValue(); inline void setValue( ::capnp::json::Value::Reader value); inline ::capnp::json::Value::Builder initValue(); inline void adoptValue(::capnp::Orphan< ::capnp::json::Value>&& value); inline ::capnp::Orphan< ::capnp::json::Value> disownValue(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Value::Field::Pipeline { public: typedef Field Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::json::Value::Pipeline getValue(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Value::Call::Reader { public: typedef Call Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasFunction() const; inline ::capnp::Text::Reader getFunction() const; inline bool hasParams() const; inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader getParams() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Value::Call::Builder { public: typedef Call Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasFunction(); inline ::capnp::Text::Builder getFunction(); inline void setFunction( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initFunction(unsigned int size); inline void adoptFunction(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownFunction(); inline bool hasParams(); inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder getParams(); inline void setParams( ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder initParams(unsigned int size); inline void adoptParams(::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>> disownParams(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Value::Call::Pipeline { public: typedef Call Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class FlattenOptions::Reader { public: typedef FlattenOptions Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasPrefix() const; inline ::capnp::Text::Reader getPrefix() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class FlattenOptions::Builder { public: typedef FlattenOptions Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasPrefix(); inline ::capnp::Text::Builder getPrefix(); inline void setPrefix( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initPrefix(unsigned int size); inline void adoptPrefix(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownPrefix(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class FlattenOptions::Pipeline { public: typedef FlattenOptions Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class DiscriminatorOptions::Reader { public: typedef DiscriminatorOptions Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasName() const; inline ::capnp::Text::Reader getName() const; inline bool hasValueName() const; inline ::capnp::Text::Reader getValueName() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class DiscriminatorOptions::Builder { public: typedef DiscriminatorOptions Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasName(); inline ::capnp::Text::Builder getName(); inline void setName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initName(unsigned int size); inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownName(); inline bool hasValueName(); inline ::capnp::Text::Builder getValueName(); inline void setValueName( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initValueName(unsigned int size); inline void adoptValueName(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownValueName(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class DiscriminatorOptions::Pipeline { public: typedef DiscriminatorOptions Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline ::capnp::json::Value::Which Value::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::json::Value::Which Value::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Value::Reader::isNull() const { return which() == Value::NULL_; } inline bool Value::Builder::isNull() { return which() == Value::NULL_; } inline ::capnp::Void Value::Reader::getNull() const { KJ_IREQUIRE((which() == Value::NULL_), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Value::Builder::getNull() { KJ_IREQUIRE((which() == Value::NULL_), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Value::Builder::setNull( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::NULL_); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isBoolean() const { return which() == Value::BOOLEAN; } inline bool Value::Builder::isBoolean() { return which() == Value::BOOLEAN; } inline bool Value::Reader::getBoolean() const { KJ_IREQUIRE((which() == Value::BOOLEAN), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS); } inline bool Value::Builder::getBoolean() { KJ_IREQUIRE((which() == Value::BOOLEAN), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS); } inline void Value::Builder::setBoolean(bool value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::BOOLEAN); _builder.setDataField( ::capnp::bounded<16>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isNumber() const { return which() == Value::NUMBER; } inline bool Value::Builder::isNumber() { return which() == Value::NUMBER; } inline double Value::Reader::getNumber() const { KJ_IREQUIRE((which() == Value::NUMBER), "Must check which() before get()ing a union member."); return _reader.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline double Value::Builder::getNumber() { KJ_IREQUIRE((which() == Value::NUMBER), "Must check which() before get()ing a union member."); return _builder.getDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Value::Builder::setNumber(double value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::NUMBER); _builder.setDataField( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Value::Reader::isString() const { return which() == Value::STRING; } inline bool Value::Builder::isString() { return which() == Value::STRING; } inline bool Value::Reader::hasString() const { if (which() != Value::STRING) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasString() { if (which() != Value::STRING) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Value::Reader::getString() const { KJ_IREQUIRE((which() == Value::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Value::Builder::getString() { KJ_IREQUIRE((which() == Value::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setString( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::STRING); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Value::Builder::initString(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::STRING); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptString( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::STRING); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Value::Builder::disownString() { KJ_IREQUIRE((which() == Value::STRING), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isArray() const { return which() == Value::ARRAY; } inline bool Value::Builder::isArray() { return which() == Value::ARRAY; } inline bool Value::Reader::hasArray() const { if (which() != Value::ARRAY) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasArray() { if (which() != Value::ARRAY) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader Value::Reader::getArray() const { KJ_IREQUIRE((which() == Value::ARRAY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder Value::Builder::getArray() { KJ_IREQUIRE((which() == Value::ARRAY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setArray( ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ARRAY); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder Value::Builder::initArray(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ARRAY); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptArray( ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::ARRAY); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>> Value::Builder::disownArray() { KJ_IREQUIRE((which() == Value::ARRAY), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isObject() const { return which() == Value::OBJECT; } inline bool Value::Builder::isObject() { return which() == Value::OBJECT; } inline bool Value::Reader::hasObject() const { if (which() != Value::OBJECT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasObject() { if (which() != Value::OBJECT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Reader Value::Reader::getObject() const { KJ_IREQUIRE((which() == Value::OBJECT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Builder Value::Builder::getObject() { KJ_IREQUIRE((which() == Value::OBJECT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setObject( ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::OBJECT); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>::Builder Value::Builder::initObject(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::OBJECT); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptObject( ::capnp::Orphan< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::OBJECT); ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>> Value::Builder::disownObject() { KJ_IREQUIRE((which() == Value::OBJECT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value::Field, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isCall() const { return which() == Value::CALL; } inline bool Value::Builder::isCall() { return which() == Value::CALL; } inline bool Value::Reader::hasCall() const { if (which() != Value::CALL) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasCall() { if (which() != Value::CALL) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::json::Value::Call::Reader Value::Reader::getCall() const { KJ_IREQUIRE((which() == Value::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::json::Value::Call::Builder Value::Builder::getCall() { KJ_IREQUIRE((which() == Value::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setCall( ::capnp::json::Value::Call::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::CALL); ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::json::Value::Call::Builder Value::Builder::initCall() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::CALL); return ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::adoptCall( ::capnp::Orphan< ::capnp::json::Value::Call>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::CALL); ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::json::Value::Call> Value::Builder::disownCall() { KJ_IREQUIRE((which() == Value::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::json::Value::Call>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Reader::isRaw() const { return which() == Value::RAW; } inline bool Value::Builder::isRaw() { return which() == Value::RAW; } inline bool Value::Reader::hasRaw() const { if (which() != Value::RAW) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Builder::hasRaw() { if (which() != Value::RAW) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Value::Reader::getRaw() const { KJ_IREQUIRE((which() == Value::RAW), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Value::Builder::getRaw() { KJ_IREQUIRE((which() == Value::RAW), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Builder::setRaw( ::capnp::Text::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::RAW); ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Value::Builder::initRaw(unsigned int size) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::RAW); return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Builder::adoptRaw( ::capnp::Orphan< ::capnp::Text>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Value::RAW); ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Value::Builder::disownRaw() { KJ_IREQUIRE((which() == Value::RAW), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Field::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Field::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Value::Field::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Value::Field::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Field::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Value::Field::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Field::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Value::Field::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Field::Reader::hasValue() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Value::Field::Builder::hasValue() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::json::Value::Reader Value::Field::Reader::getValue() const { return ::capnp::_::PointerHelpers< ::capnp::json::Value>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::json::Value::Builder Value::Field::Builder::getValue() { return ::capnp::_::PointerHelpers< ::capnp::json::Value>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::json::Value::Pipeline Value::Field::Pipeline::getValue() { return ::capnp::json::Value::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Value::Field::Builder::setValue( ::capnp::json::Value::Reader value) { ::capnp::_::PointerHelpers< ::capnp::json::Value>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::json::Value::Builder Value::Field::Builder::initValue() { return ::capnp::_::PointerHelpers< ::capnp::json::Value>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Value::Field::Builder::adoptValue( ::capnp::Orphan< ::capnp::json::Value>&& value) { ::capnp::_::PointerHelpers< ::capnp::json::Value>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::json::Value> Value::Field::Builder::disownValue() { return ::capnp::_::PointerHelpers< ::capnp::json::Value>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool Value::Call::Reader::hasFunction() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Value::Call::Builder::hasFunction() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Value::Call::Reader::getFunction() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Value::Call::Builder::getFunction() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Value::Call::Builder::setFunction( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Value::Call::Builder::initFunction(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Value::Call::Builder::adoptFunction( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Value::Call::Builder::disownFunction() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Value::Call::Reader::hasParams() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Value::Call::Builder::hasParams() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader Value::Call::Reader::getParams() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder Value::Call::Builder::getParams() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Value::Call::Builder::setParams( ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>::Builder Value::Call::Builder::initParams(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Value::Call::Builder::adoptParams( ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>> Value::Call::Builder::disownParams() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::json::Value, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline bool FlattenOptions::Reader::hasPrefix() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool FlattenOptions::Builder::hasPrefix() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader FlattenOptions::Reader::getPrefix() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), ::capnp::schemas::bp_c4df13257bc2ea61 + 34); } inline ::capnp::Text::Builder FlattenOptions::Builder::getPrefix() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), ::capnp::schemas::bp_c4df13257bc2ea61 + 34); } inline void FlattenOptions::Builder::setPrefix( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder FlattenOptions::Builder::initPrefix(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void FlattenOptions::Builder::adoptPrefix( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> FlattenOptions::Builder::disownPrefix() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool DiscriminatorOptions::Reader::hasName() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool DiscriminatorOptions::Builder::hasName() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader DiscriminatorOptions::Reader::getName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder DiscriminatorOptions::Builder::getName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void DiscriminatorOptions::Builder::setName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder DiscriminatorOptions::Builder::initName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void DiscriminatorOptions::Builder::adoptName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> DiscriminatorOptions::Builder::disownName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool DiscriminatorOptions::Reader::hasValueName() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool DiscriminatorOptions::Builder::hasValueName() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader DiscriminatorOptions::Reader::getValueName() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder DiscriminatorOptions::Builder::getValueName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void DiscriminatorOptions::Builder::setValueName( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder DiscriminatorOptions::Builder::initValueName(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void DiscriminatorOptions::Builder::adoptValueName( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> DiscriminatorOptions::Builder::disownValueName() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compat/json.capnp0000644000175000017500000001256514527152321022124 0ustar00kentonkenton00000000000000# Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0x8ef99297a43a5e34; $import "/capnp/c++.capnp".namespace("capnp::json"); struct Value { union { null @0 :Void; boolean @1 :Bool; number @2 :Float64; string @3 :Text; array @4 :List(Value); object @5 :List(Field); # Standard JSON values. call @6 :Call; # Non-standard: A "function call", applying a named function (named by a single identifier) # to a parameter list. Examples: # # BinData(0, "Zm9vCg==") # ISODate("2015-04-15T08:44:50.218Z") # # Mongo DB users will recognize the above as exactly the syntax Mongo uses to represent BSON # "binary" and "date" types in text, since JSON has no analog of these. This is basically the # reason this extension exists. We do NOT recommend using `call` unless you specifically need # to be compatible with some silly format that uses this syntax. raw @7 :Text; # Used to indicate that the text should be written directly to the output without # modifications. Use this if you have an already serialized JSON value and don't want # to feel the cost of deserializing the value just to serialize it again. # # The parser will never produce a `raw` value -- this is only useful for serialization. # # WARNING: You MUST ensure that the value is valid stand-alone JSOn. It will not be verified. # Invalid JSON could mjake the whole message unparsable. Worse, a malicious raw value could # perform JSON injection attacks. Make sure that the value was produced by a trustworthy JSON # encoder. } struct Field { name @0 :Text; value @1 :Value; } struct Call { function @0 :Text; params @1 :List(Value); } } # ======================================================================================== # Annotations to control parsing. Typical usage: # # using Json = import "/capnp/compat/json.capnp"; # # And then later on: # # myField @0 :Text $Json.name("my_field"); annotation name @0xfa5b1fd61c2e7c3d (field, enumerant, method, group, union) :Text; # Define an alternative name to use when encoding the given item in JSON. This can be used, for # example, to use snake_case names where needed, even though Cap'n Proto uses strictly camelCase. # # (However, because JSON is derived from JavaScript, you *should* use camelCase names when # defining JSON-based APIs. But, when supporting a pre-existing API you may not have a choice.) annotation flatten @0x82d3e852af0336bf (field, group, union) :FlattenOptions; # Specifies that an aggregate field should be flattened into its parent. # # In order to flatten a member of a union, the union (or, for an anonymous union, the parent # struct type) must have the $jsonDiscriminator annotation. # # TODO(someday): Maybe support "flattening" a List(Value.Field) as a way to support unknown JSON # fields? struct FlattenOptions { prefix @0 :Text = ""; # Optional: Adds the given prefix to flattened field names. } annotation discriminator @0xcfa794e8d19a0162 (struct, union) :DiscriminatorOptions; # Specifies that a union's variant will be decided not by which fields are present, but instead # by a special discriminator field. The value of the discriminator field is a string naming which # variant is active. This allows the members of the union to have the $jsonFlatten annotation, or # to all have the same name. struct DiscriminatorOptions { name @0 :Text; # The name of the discriminator field. Defaults to matching the name of the union. valueName @1 :Text; # If non-null, specifies that the union's value shall have the given field name, rather than the # value's name. In this case the union's variant can only be determined by looking at the # discriminant field, not by inspecting which value field is present. # # It is an error to use `valueName` while also declaring some variants as $flatten. } annotation base64 @0xd7d879450a253e4b (field) :Void; # Place on a field of type `Data` to indicate that its JSON representation is a Base64 string. annotation hex @0xf061e22f0ae5c7b5 (field) :Void; # Place on a field of type `Data` to indicate that its JSON representation is a hex string. annotation notification @0xa0a054dea32fd98c (method) :Void; # Indicates that this method is a JSON-RPC "notification", meaning it expects no response. capnproto-c++-1.1.0/src/capnp/compat/websocket-rpc-test.c++0000644000175000017500000001076014712011043024131 0ustar00kentonkenton00000000000000// Copyright (c) 2021 Ian Denhardt and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "websocket-rpc.h" #include #include KJ_TEST("WebSocketMessageStream") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe = kj::newWebSocketPipe(); auto msgStreamA = capnp::WebSocketMessageStream(*pipe.ends[0]); auto msgStreamB = capnp::WebSocketMessageStream(*pipe.ends[1]); // Make a message, fill it with some stuff capnp::MallocMessageBuilder originalMsg; auto object = originalMsg.initRoot().initStructList(10); object[0].setTextField("Test"); object[1].initStructField().setTextField("A string"); object[2].setTextField("Another field"); object[3].setInt64Field(42); auto originalSegments = originalMsg.getSegmentsForOutput(); // Send the message across the websocket, make sure it comes out unharmed. auto writePromise = msgStreamA.writeMessage(nullptr, originalSegments); msgStreamB.tryReadMessage(nullptr) .then([&](auto maybeResult) -> kj::Promise { KJ_IF_MAYBE(result, maybeResult) { KJ_ASSERT(result->fds.size() == 0); KJ_ASSERT(result->reader->getSegment(originalSegments.size()) == nullptr); for(size_t i = 0; i < originalSegments.size(); i++) { auto oldSegment = originalSegments[i]; auto newSegment = result->reader->getSegment(i); KJ_ASSERT(oldSegment.size() == newSegment.size()); KJ_ASSERT(memcmp( &oldSegment[0], &newSegment[0], oldSegment.size() * sizeof(capnp::word) ) == 0); } return kj::READY_NOW; } else { KJ_FAIL_ASSERT("Reading first message failed"); } }).wait(waitScope); writePromise.wait(waitScope); // Close the websocket, and make sure the other end gets nullptr when reading. auto endPromise = msgStreamA.end(); msgStreamB.tryReadMessage(nullptr).then([](auto maybe) -> kj::Promise { KJ_IF_MAYBE(segments, maybe) { KJ_FAIL_ASSERT("Should have gotten nullptr after websocket was closed"); } return kj::READY_NOW; }).wait(waitScope); endPromise.wait(waitScope); } KJ_TEST("WebSocketMessageStreamByteCount") { kj::EventLoop loop; kj::WaitScope waitScope(loop); auto pipe1 = kj::newWebSocketPipe(); auto pipe2 = kj::newWebSocketPipe(); auto msgStreamA = capnp::WebSocketMessageStream(*pipe1.ends[0]); auto msgStreamB = capnp::WebSocketMessageStream(*pipe2.ends[1]); auto pumpTask = pipe1.ends[1]->pumpTo(*pipe2.ends[0]); capnp::MallocMessageBuilder originalMsg; auto object = originalMsg.initRoot().initStructList(10); object[0].setTextField("Test"); object[1].initStructField().setTextField("A string"); object[2].setTextField("Another field"); object[3].setInt64Field(42); auto originalSegments = originalMsg.getSegmentsForOutput(); auto writePromise = msgStreamA.writeMessage(nullptr, originalSegments); msgStreamB.tryReadMessage(nullptr).wait(waitScope); writePromise.wait(waitScope); auto endPromise = msgStreamA.end(); msgStreamB.tryReadMessage(nullptr).wait(waitScope); pumpTask.wait(waitScope); endPromise.wait(waitScope); KJ_EXPECT(pipe1.ends[0]->sentByteCount() == 2585); KJ_EXPECT(pipe1.ends[1]->receivedByteCount() == 2585); KJ_EXPECT(pipe2.ends[0]->sentByteCount() == 2585); KJ_EXPECT(pipe2.ends[1]->receivedByteCount() == 2585); } capnproto-c++-1.1.0/src/capnp/compat/json.capnp.c++0000644000175000017500000007041614712011043022461 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: json.capnp #include "json.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<152> b_a3fa7845f919dd83 = { { 0, 0, 0, 0, 5, 0, 6, 0, 131, 221, 25, 249, 69, 120, 250, 163, 24, 0, 0, 0, 1, 0, 2, 0, 52, 94, 58, 164, 151, 146, 249, 142, 1, 0, 7, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 242, 0, 0, 0, 33, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 199, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 86, 97, 108, 117, 101, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 223, 157, 214, 53, 231, 38, 16, 227, 9, 0, 0, 0, 50, 0, 0, 0, 72, 61, 201, 161, 236, 246, 217, 160, 5, 0, 0, 0, 42, 0, 0, 0, 70, 105, 101, 108, 100, 0, 0, 0, 67, 97, 108, 108, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 3, 0, 1, 0, 216, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 16, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 3, 0, 1, 0, 220, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 3, 0, 1, 0, 224, 0, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 3, 0, 1, 0, 228, 0, 0, 0, 2, 0, 1, 0, 4, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 3, 0, 1, 0, 248, 0, 0, 0, 2, 0, 1, 0, 5, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 3, 0, 1, 0, 12, 1, 0, 0, 2, 0, 1, 0, 6, 0, 249, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 3, 0, 1, 0, 16, 1, 0, 0, 2, 0, 1, 0, 7, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 3, 0, 1, 0, 20, 1, 0, 0, 2, 0, 1, 0, 110, 117, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 111, 111, 108, 101, 97, 110, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 117, 109, 98, 101, 114, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 105, 110, 103, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 114, 114, 97, 121, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 131, 221, 25, 249, 69, 120, 250, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 98, 106, 101, 99, 116, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 223, 157, 214, 53, 231, 38, 16, 227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 108, 108, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 72, 61, 201, 161, 236, 246, 217, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 97, 119, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_a3fa7845f919dd83 = b_a3fa7845f919dd83.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_a3fa7845f919dd83[] = { &s_a0d9f6eca1c93d48, &s_a3fa7845f919dd83, &s_e31026e735d69ddf, }; static const uint16_t m_a3fa7845f919dd83[] = {4, 1, 6, 0, 2, 5, 7, 3}; static const uint16_t i_a3fa7845f919dd83[] = {0, 1, 2, 3, 4, 5, 6, 7}; const ::capnp::_::RawSchema s_a3fa7845f919dd83 = { 0xa3fa7845f919dd83, b_a3fa7845f919dd83.words, 152, d_a3fa7845f919dd83, m_a3fa7845f919dd83, 3, 8, i_a3fa7845f919dd83, nullptr, nullptr, { &s_a3fa7845f919dd83, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_e31026e735d69ddf = { { 0, 0, 0, 0, 5, 0, 6, 0, 223, 157, 214, 53, 231, 38, 16, 227, 30, 0, 0, 0, 1, 0, 0, 0, 131, 221, 25, 249, 69, 120, 250, 163, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 34, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 86, 97, 108, 117, 101, 46, 70, 105, 101, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 131, 221, 25, 249, 69, 120, 250, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e31026e735d69ddf = b_e31026e735d69ddf.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_e31026e735d69ddf[] = { &s_a3fa7845f919dd83, }; static const uint16_t m_e31026e735d69ddf[] = {0, 1}; static const uint16_t i_e31026e735d69ddf[] = {0, 1}; const ::capnp::_::RawSchema s_e31026e735d69ddf = { 0xe31026e735d69ddf, b_e31026e735d69ddf.words, 49, d_e31026e735d69ddf, m_e31026e735d69ddf, 1, 2, i_e31026e735d69ddf, nullptr, nullptr, { &s_e31026e735d69ddf, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<54> b_a0d9f6eca1c93d48 = { { 0, 0, 0, 0, 5, 0, 6, 0, 72, 61, 201, 161, 236, 246, 217, 160, 30, 0, 0, 0, 1, 0, 0, 0, 131, 221, 25, 249, 69, 120, 250, 163, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 26, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 86, 97, 108, 117, 101, 46, 67, 97, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 72, 0, 0, 0, 2, 0, 1, 0, 102, 117, 110, 99, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 131, 221, 25, 249, 69, 120, 250, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_a0d9f6eca1c93d48 = b_a0d9f6eca1c93d48.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_a0d9f6eca1c93d48[] = { &s_a3fa7845f919dd83, }; static const uint16_t m_a0d9f6eca1c93d48[] = {0, 1}; static const uint16_t i_a0d9f6eca1c93d48[] = {0, 1}; const ::capnp::_::RawSchema s_a0d9f6eca1c93d48 = { 0xa0d9f6eca1c93d48, b_a0d9f6eca1c93d48.words, 54, d_a0d9f6eca1c93d48, m_a0d9f6eca1c93d48, 1, 2, i_a0d9f6eca1c93d48, nullptr, nullptr, { &s_a0d9f6eca1c93d48, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<21> b_fa5b1fd61c2e7c3d = { { 0, 0, 0, 0, 5, 0, 6, 0, 61, 124, 46, 28, 214, 31, 91, 250, 24, 0, 0, 0, 5, 0, 232, 2, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 110, 97, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_fa5b1fd61c2e7c3d = b_fa5b1fd61c2e7c3d.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_fa5b1fd61c2e7c3d = { 0xfa5b1fd61c2e7c3d, b_fa5b1fd61c2e7c3d.words, 21, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_fa5b1fd61c2e7c3d, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<21> b_82d3e852af0336bf = { { 0, 0, 0, 0, 5, 0, 6, 0, 191, 54, 3, 175, 82, 232, 211, 130, 24, 0, 0, 0, 5, 0, 224, 0, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 2, 1, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 102, 108, 97, 116, 116, 101, 110, 0, 0, 0, 0, 0, 1, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 97, 234, 194, 123, 37, 19, 223, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_82d3e852af0336bf = b_82d3e852af0336bf.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_82d3e852af0336bf = { 0x82d3e852af0336bf, b_82d3e852af0336bf.words, 21, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_82d3e852af0336bf, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<35> b_c4df13257bc2ea61 = { { 0, 0, 0, 0, 5, 0, 6, 0, 97, 234, 194, 123, 37, 19, 223, 196, 24, 0, 0, 0, 1, 0, 0, 0, 52, 94, 58, 164, 151, 146, 249, 142, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 58, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 70, 108, 97, 116, 116, 101, 110, 79, 112, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 112, 114, 101, 102, 105, 120, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c4df13257bc2ea61 = b_c4df13257bc2ea61.words; #if !CAPNP_LITE static const uint16_t m_c4df13257bc2ea61[] = {0}; static const uint16_t i_c4df13257bc2ea61[] = {0}; const ::capnp::_::RawSchema s_c4df13257bc2ea61 = { 0xc4df13257bc2ea61, b_c4df13257bc2ea61.words, 35, nullptr, m_c4df13257bc2ea61, 0, 1, i_c4df13257bc2ea61, nullptr, nullptr, { &s_c4df13257bc2ea61, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<22> b_cfa794e8d19a0162 = { { 0, 0, 0, 0, 5, 0, 6, 0, 98, 1, 154, 209, 232, 148, 167, 207, 24, 0, 0, 0, 5, 0, 80, 0, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 50, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 100, 105, 115, 99, 114, 105, 109, 105, 110, 97, 116, 111, 114, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 25, 83, 62, 41, 12, 194, 248, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_cfa794e8d19a0162 = b_cfa794e8d19a0162.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_cfa794e8d19a0162 = { 0xcfa794e8d19a0162, b_cfa794e8d19a0162.words, 22, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_cfa794e8d19a0162, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_c2f8c20c293e5319 = { { 0, 0, 0, 0, 5, 0, 6, 0, 25, 83, 62, 41, 12, 194, 248, 194, 24, 0, 0, 0, 1, 0, 0, 0, 52, 94, 58, 164, 151, 146, 249, 142, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 106, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 68, 105, 115, 99, 114, 105, 109, 105, 110, 97, 116, 111, 114, 79, 112, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 78, 97, 109, 101, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c2f8c20c293e5319 = b_c2f8c20c293e5319.words; #if !CAPNP_LITE static const uint16_t m_c2f8c20c293e5319[] = {0, 1}; static const uint16_t i_c2f8c20c293e5319[] = {0, 1}; const ::capnp::_::RawSchema s_c2f8c20c293e5319 = { 0xc2f8c20c293e5319, b_c2f8c20c293e5319.words, 51, nullptr, m_c2f8c20c293e5319, 0, 2, i_c2f8c20c293e5319, nullptr, nullptr, { &s_c2f8c20c293e5319, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<21> b_d7d879450a253e4b = { { 0, 0, 0, 0, 5, 0, 6, 0, 75, 62, 37, 10, 69, 121, 216, 215, 24, 0, 0, 0, 5, 0, 32, 0, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 98, 97, 115, 101, 54, 52, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d7d879450a253e4b = b_d7d879450a253e4b.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_d7d879450a253e4b = { 0xd7d879450a253e4b, b_d7d879450a253e4b.words, 21, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_d7d879450a253e4b, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<21> b_f061e22f0ae5c7b5 = { { 0, 0, 0, 0, 5, 0, 6, 0, 181, 199, 229, 10, 47, 226, 97, 240, 24, 0, 0, 0, 5, 0, 32, 0, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 104, 101, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f061e22f0ae5c7b5 = b_f061e22f0ae5c7b5.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_f061e22f0ae5c7b5 = { 0xf061e22f0ae5c7b5, b_f061e22f0ae5c7b5.words, 21, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_f061e22f0ae5c7b5, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<22> b_a0a054dea32fd98c = { { 0, 0, 0, 0, 5, 0, 6, 0, 140, 217, 47, 163, 222, 84, 160, 160, 24, 0, 0, 0, 5, 0, 0, 2, 52, 94, 58, 164, 151, 146, 249, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 99, 111, 109, 112, 97, 116, 47, 106, 115, 111, 110, 46, 99, 97, 112, 110, 112, 58, 110, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_a0a054dea32fd98c = b_a0a054dea32fd98c.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_a0a054dea32fd98c = { 0xa0a054dea32fd98c, b_a0a054dea32fd98c.words, 22, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_a0a054dea32fd98c, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace json { // Value #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Value::_capnpPrivate::dataWordSize; constexpr uint16_t Value::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Value::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Value::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Value::Field #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Value::Field::_capnpPrivate::dataWordSize; constexpr uint16_t Value::Field::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Value::Field::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Value::Field::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Value::Call #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Value::Call::_capnpPrivate::dataWordSize; constexpr uint16_t Value::Call::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Value::Call::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Value::Call::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // FlattenOptions #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t FlattenOptions::_capnpPrivate::dataWordSize; constexpr uint16_t FlattenOptions::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind FlattenOptions::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* FlattenOptions::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // DiscriminatorOptions #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t DiscriminatorOptions::_capnpPrivate::dataWordSize; constexpr uint16_t DiscriminatorOptions::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind DiscriminatorOptions::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* DiscriminatorOptions::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/compat/json.c++0000644000175000017500000014630514712011043021362 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "json.h" #include #include #include #include #include #include #include namespace capnp { struct JsonCodec::Impl { bool prettyPrint = false; HasMode hasMode = HasMode::NON_NULL; size_t maxNestingDepth = 64; bool rejectUnknownFields = false; kj::HashMap typeHandlers; kj::HashMap fieldHandlers; kj::HashMap>> annotatedHandlers; kj::HashMap> annotatedEnumHandlers; kj::StringTree encodeRaw(JsonValue::Reader value, uint indent, bool& multiline, bool hasPrefix) const { switch (value.which()) { case JsonValue::NULL_: return kj::strTree("null"); case JsonValue::BOOLEAN: return kj::strTree(value.getBoolean()); case JsonValue::NUMBER: return kj::strTree(value.getNumber()); case JsonValue::STRING: return kj::strTree(encodeString(value.getString())); case JsonValue::ARRAY: { auto array = value.getArray(); uint subIndent = indent + (array.size() > 1); bool childMultiline = false; auto encodedElements = KJ_MAP(element, array) { return encodeRaw(element, subIndent, childMultiline, false); }; return kj::strTree('[', encodeList( kj::mv(encodedElements), childMultiline, indent, multiline, hasPrefix), ']'); } case JsonValue::OBJECT: { auto object = value.getObject(); uint subIndent = indent + (object.size() > 1); bool childMultiline = false; kj::StringPtr colon = prettyPrint ? ": " : ":"; auto encodedElements = KJ_MAP(field, object) { return kj::strTree( encodeString(field.getName()), colon, encodeRaw(field.getValue(), subIndent, childMultiline, true)); }; return kj::strTree('{', encodeList( kj::mv(encodedElements), childMultiline, indent, multiline, hasPrefix), '}'); } case JsonValue::CALL: { auto call = value.getCall(); auto params = call.getParams(); uint subIndent = indent + (params.size() > 1); bool childMultiline = false; auto encodedElements = KJ_MAP(element, params) { return encodeRaw(element, subIndent, childMultiline, false); }; return kj::strTree(call.getFunction(), '(', encodeList( kj::mv(encodedElements), childMultiline, indent, multiline, true), ')'); } case JsonValue::RAW: { return kj::strTree(value.getRaw()); } } KJ_FAIL_ASSERT("unknown JsonValue type", static_cast(value.which())); } kj::String encodeString(kj::StringPtr chars) const { static const char HEXDIGITS[] = "0123456789abcdef"; kj::Vector escaped(chars.size() + 3); escaped.add('"'); for (char c: chars) { switch (c) { case '\"': escaped.addAll(kj::StringPtr("\\\"")); break; case '\\': escaped.addAll(kj::StringPtr("\\\\")); break; case '\b': escaped.addAll(kj::StringPtr("\\b")); break; case '\f': escaped.addAll(kj::StringPtr("\\f")); break; case '\n': escaped.addAll(kj::StringPtr("\\n")); break; case '\r': escaped.addAll(kj::StringPtr("\\r")); break; case '\t': escaped.addAll(kj::StringPtr("\\t")); break; default: if (static_cast(c) < 0x20) { escaped.addAll(kj::StringPtr("\\u00")); uint8_t c2 = c; escaped.add(HEXDIGITS[c2 / 16]); escaped.add(HEXDIGITS[c2 % 16]); } else { escaped.add(c); } break; } } escaped.add('"'); escaped.add('\0'); return kj::String(escaped.releaseAsArray()); } kj::StringTree encodeList(kj::Array elements, bool hasMultilineElement, uint indent, bool& multiline, bool hasPrefix) const { size_t maxChildSize = 0; for (auto& e: elements) maxChildSize = kj::max(maxChildSize, e.size()); kj::StringPtr prefix; kj::StringPtr delim; kj::StringPtr suffix; kj::String ownPrefix; kj::String ownDelim; if (!prettyPrint) { // No whitespace. delim = ","; prefix = ""; suffix = ""; } else if ((elements.size() > 1) && (hasMultilineElement || maxChildSize > 50)) { // If the array contained any multi-line elements, OR it contained sufficiently long // elements, then put each element on its own line. auto indentSpace = kj::repeat(' ', (indent + 1) * 2); delim = ownDelim = kj::str(",\n", indentSpace); multiline = true; if (hasPrefix) { // We're producing a multi-line list, and the first line has some garbage in front of it. // Therefore, move the first element to the next line. prefix = ownPrefix = kj::str("\n", indentSpace); } else { prefix = " "; } suffix = " "; } else { // Put everything on one line, but add spacing between elements for legibility. delim = ", "; prefix = ""; suffix = ""; } return kj::strTree(prefix, kj::StringTree(kj::mv(elements), delim), suffix); } }; JsonCodec::JsonCodec() : impl(kj::heap()) {} JsonCodec::~JsonCodec() noexcept(false) {} void JsonCodec::setPrettyPrint(bool enabled) { impl->prettyPrint = enabled; } void JsonCodec::setMaxNestingDepth(size_t maxNestingDepth) { impl->maxNestingDepth = maxNestingDepth; } void JsonCodec::setHasMode(HasMode mode) { impl->hasMode = mode; } void JsonCodec::setRejectUnknownFields(bool enabled) { impl->rejectUnknownFields = enabled; } kj::String JsonCodec::encode(DynamicValue::Reader value, Type type) const { MallocMessageBuilder message; auto json = message.getRoot(); encode(value, type, json); return encodeRaw(json); } void JsonCodec::decode(kj::ArrayPtr input, DynamicStruct::Builder output) const { MallocMessageBuilder message; auto json = message.getRoot(); decodeRaw(input, json); decode(json, output); } Orphan JsonCodec::decode( kj::ArrayPtr input, Type type, Orphanage orphanage) const { MallocMessageBuilder message; auto json = message.getRoot(); decodeRaw(input, json); return decode(json, type, orphanage); } kj::String JsonCodec::encodeRaw(JsonValue::Reader value) const { bool multiline = false; return impl->encodeRaw(value, 0, multiline, false).flatten(); } void JsonCodec::encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const { // TODO(someday): For interfaces, check for handlers on superclasses, per documentation... // TODO(someday): For branded types, should we check for handlers on the generic? // TODO(someday): Allow registering handlers for "all structs", "all lists", etc? KJ_IF_MAYBE(handler, impl->typeHandlers.find(type)) { (*handler)->encodeBase(*this, input, output); return; } switch (type.which()) { case schema::Type::VOID: output.setNull(); break; case schema::Type::BOOL: output.setBoolean(input.as()); break; case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: output.setNumber(input.as()); break; case schema::Type::FLOAT32: case schema::Type::FLOAT64: { double value = input.as(); // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. if (kj::inf() == value) { output.setString("Infinity"); } else if (-kj::inf() == value) { output.setString("-Infinity"); } else if (kj::isNaN(value)) { output.setString("NaN"); } else { output.setNumber(value); } } break; case schema::Type::INT64: output.setString(kj::str(input.as())); break; case schema::Type::UINT64: output.setString(kj::str(input.as())); break; case schema::Type::TEXT: output.setString(kj::str(input.as())); break; case schema::Type::DATA: { // Turn into array of byte values. Yep, this is pretty ugly. People really need to override // this with a handler. auto bytes = input.as(); auto array = output.initArray(bytes.size()); for (auto i: kj::indices(bytes)) { array[i].setNumber(bytes[i]); } break; } case schema::Type::LIST: { auto list = input.as(); auto elementType = type.asList().getElementType(); auto array = output.initArray(list.size()); for (auto i: kj::indices(list)) { encode(list[i], elementType, array[i]); } break; } case schema::Type::ENUM: { auto e = input.as(); KJ_IF_MAYBE(symbol, e.getEnumerant()) { output.setString(symbol->getProto().getName()); } else { output.setNumber(e.getRaw()); } break; } case schema::Type::STRUCT: { auto structValue = input.as(); auto nonUnionFields = structValue.getSchema().getNonUnionFields(); KJ_STACK_ARRAY(bool, hasField, nonUnionFields.size(), 32, 128); uint fieldCount = 0; for (auto i: kj::indices(nonUnionFields)) { fieldCount += (hasField[i] = structValue.has(nonUnionFields[i], impl->hasMode)); } // We try to write the union field, if any, in proper order with the rest. auto which = structValue.which(); bool unionFieldIsNull = false; KJ_IF_MAYBE(field, which) { // Even if the union field is null, if it is not the default field of the union then we // have to print it anyway. unionFieldIsNull = !structValue.has(*field, impl->hasMode); if (field->getProto().getDiscriminantValue() != 0 || !unionFieldIsNull) { ++fieldCount; } else { which = nullptr; } } auto object = output.initObject(fieldCount); size_t pos = 0; for (auto i: kj::indices(nonUnionFields)) { auto field = nonUnionFields[i]; KJ_IF_MAYBE(unionField, which) { if (unionField->getIndex() < field.getIndex()) { auto outField = object[pos++]; outField.setName(unionField->getProto().getName()); if (unionFieldIsNull) { outField.initValue().setNull(); } else { encodeField(*unionField, structValue.get(*unionField), outField.initValue()); } which = nullptr; } } if (hasField[i]) { auto outField = object[pos++]; outField.setName(field.getProto().getName()); encodeField(field, structValue.get(field), outField.initValue()); } } if (which != nullptr) { // Union field not printed yet; must be last. auto unionField = KJ_ASSERT_NONNULL(which); auto outField = object[pos++]; outField.setName(unionField.getProto().getName()); if (unionFieldIsNull) { outField.initValue().setNull(); } else { encodeField(unionField, structValue.get(unionField), outField.initValue()); } } KJ_ASSERT(pos == fieldCount); break; } case schema::Type::INTERFACE: KJ_FAIL_REQUIRE("don't know how to JSON-encode capabilities; " "please register a JsonCodec::Handler for this"); case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("don't know how to JSON-encode AnyPointer; " "please register a JsonCodec::Handler for this"); } } void JsonCodec::encodeField(StructSchema::Field field, DynamicValue::Reader input, JsonValue::Builder output) const { KJ_IF_MAYBE(handler, impl->fieldHandlers.find(field)) { (*handler)->encodeBase(*this, input, output); return; } encode(input, field.getType(), output); } Orphan JsonCodec::decodeArray(List::Reader input, ListSchema type, Orphanage orphanage) const { auto orphan = orphanage.newOrphan(type, input.size()); auto output = orphan.get(); for (auto i: kj::indices(input)) { output.adopt(i, decode(input[i], type.getElementType(), orphanage)); } return orphan; } void JsonCodec::decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const { KJ_REQUIRE(input.isObject(), "Expected object value") { return; } for (auto field: input.getObject()) { KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) { decodeField(*fieldSchema, field.getValue(), orphanage, output); } else { KJ_REQUIRE(!impl->rejectUnknownFields, "Unknown field", field.getName()); } } } void JsonCodec::decodeField(StructSchema::Field fieldSchema, JsonValue::Reader fieldValue, Orphanage orphanage, DynamicStruct::Builder output) const { auto fieldType = fieldSchema.getType(); KJ_IF_MAYBE(handler, impl->fieldHandlers.find(fieldSchema)) { output.adopt(fieldSchema, (*handler)->decodeBase(*this, fieldValue, fieldType, orphanage)); } else { output.adopt(fieldSchema, decode(fieldValue, fieldType, orphanage)); } } void JsonCodec::decode(JsonValue::Reader input, DynamicStruct::Builder output) const { auto type = output.getSchema(); KJ_IF_MAYBE(handler, impl->typeHandlers.find(type)) { return (*handler)->decodeStructBase(*this, input, output); } decodeObject(input, type, Orphanage::getForMessageContaining(output), output); } Orphan JsonCodec::decode( JsonValue::Reader input, Type type, Orphanage orphanage) const { KJ_IF_MAYBE(handler, impl->typeHandlers.find(type)) { return (*handler)->decodeBase(*this, input, type, orphanage); } switch(type.which()) { case schema::Type::VOID: return capnp::VOID; case schema::Type::BOOL: switch (input.which()) { case JsonValue::BOOLEAN: return input.getBoolean(); default: KJ_FAIL_REQUIRE("Expected boolean value"); } case schema::Type::INT8: case schema::Type::INT16: case schema::Type::INT32: case schema::Type::INT64: // Relies on range check in DynamicValue::Reader::as switch (input.which()) { case JsonValue::NUMBER: return input.getNumber(); case JsonValue::STRING: return input.getString().parseAs(); default: KJ_FAIL_REQUIRE("Expected integer value"); } case schema::Type::UINT8: case schema::Type::UINT16: case schema::Type::UINT32: case schema::Type::UINT64: // Relies on range check in DynamicValue::Reader::as switch (input.which()) { case JsonValue::NUMBER: return input.getNumber(); case JsonValue::STRING: return input.getString().parseAs(); default: KJ_FAIL_REQUIRE("Expected integer value"); } case schema::Type::FLOAT32: case schema::Type::FLOAT64: switch (input.which()) { case JsonValue::NULL_: return kj::nan(); case JsonValue::NUMBER: return input.getNumber(); case JsonValue::STRING: return input.getString().parseAs(); default: KJ_FAIL_REQUIRE("Expected float value"); } case schema::Type::TEXT: switch (input.which()) { case JsonValue::STRING: return orphanage.newOrphanCopy(input.getString()); default: KJ_FAIL_REQUIRE("Expected text value"); } case schema::Type::DATA: switch (input.which()) { case JsonValue::ARRAY: { auto array = input.getArray(); auto orphan = orphanage.newOrphan(array.size()); auto data = orphan.get(); for (auto i: kj::indices(array)) { auto x = array[i].getNumber(); KJ_REQUIRE(byte(x) == x, "Number in byte array is not an integer in [0, 255]"); data[i] = x; } return kj::mv(orphan); } default: KJ_FAIL_REQUIRE("Expected data value"); } case schema::Type::LIST: switch (input.which()) { case JsonValue::ARRAY: return decodeArray(input.getArray(), type.asList(), orphanage); default: KJ_FAIL_REQUIRE("Expected list value") { break; } return orphanage.newOrphan(type.asList(), 0); } case schema::Type::ENUM: switch (input.which()) { case JsonValue::STRING: return DynamicEnum(type.asEnum().getEnumerantByName(input.getString())); default: KJ_FAIL_REQUIRE("Expected enum value") { break; } return DynamicEnum(type.asEnum(), 0); } case schema::Type::STRUCT: { auto structType = type.asStruct(); auto orphan = orphanage.newOrphan(structType); decodeObject(input, structType, orphanage, orphan.get()); return kj::mv(orphan); } case schema::Type::INTERFACE: KJ_FAIL_REQUIRE("don't know how to JSON-decode capabilities; " "please register a JsonCodec::Handler for this"); case schema::Type::ANY_POINTER: KJ_FAIL_REQUIRE("don't know how to JSON-decode AnyPointer; " "please register a JsonCodec::Handler for this"); } KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT; } // ----------------------------------------------------------------------------- namespace { class Input { public: Input(kj::ArrayPtr input) : wrapped(input) {} bool exhausted() { return wrapped.size() == 0 || wrapped.front() == '\0'; } char nextChar() { KJ_REQUIRE(!exhausted(), "JSON message ends prematurely."); return wrapped.front(); } void advance(size_t numBytes = 1) { KJ_REQUIRE(numBytes <= wrapped.size(), "JSON message ends prematurely."); wrapped = kj::arrayPtr(wrapped.begin() + numBytes, wrapped.end()); } void advanceTo(const char *newPos) { KJ_REQUIRE(wrapped.begin() <= newPos && newPos < wrapped.end(), "JSON message ends prematurely."); wrapped = kj::arrayPtr(newPos, wrapped.end()); } kj::ArrayPtr consume(size_t numBytes = 1) { auto originalPos = wrapped.begin(); advance(numBytes); return kj::arrayPtr(originalPos, wrapped.begin()); } void consume(char expected) { char current = nextChar(); KJ_REQUIRE(current == expected, "Unexpected input in JSON message."); advance(); } void consume(kj::ArrayPtr expected) { KJ_REQUIRE(wrapped.size() >= expected.size()); auto prefix = wrapped.slice(0, expected.size()); KJ_REQUIRE(prefix == expected, "Unexpected input in JSON message."); advance(expected.size()); } bool tryConsume(char expected) { bool found = !exhausted() && nextChar() == expected; if (found) { advance(); } return found; } template void consumeOne(Predicate&& predicate) { char current = nextChar(); KJ_REQUIRE(predicate(current), "Unexpected input in JSON message."); advance(); } template kj::ArrayPtr consumeWhile(Predicate&& predicate) { auto originalPos = wrapped.begin(); while (!exhausted() && predicate(nextChar())) { advance(); } return kj::arrayPtr(originalPos, wrapped.begin()); } template // Function kj::ArrayPtr consumeCustom(F&& f) { // Allows consuming in a custom manner without exposing the wrapped ArrayPtr. auto originalPos = wrapped.begin(); f(*this); return kj::arrayPtr(originalPos, wrapped.begin()); } void consumeWhitespace() { consumeWhile([](char chr) { return ( chr == ' ' || chr == '\n' || chr == '\r' || chr == '\t' ); }); } private: kj::ArrayPtr wrapped; }; // class Input class Parser { public: Parser(size_t maxNestingDepth, kj::ArrayPtr input) : maxNestingDepth(maxNestingDepth), input(input), nestingDepth(0) {} void parseValue(JsonValue::Builder& output) { input.consumeWhitespace(); KJ_DEFER(input.consumeWhitespace()); KJ_REQUIRE(!input.exhausted(), "JSON message ends prematurely."); switch (input.nextChar()) { case 'n': input.consume(kj::StringPtr("null")); output.setNull(); break; case 'f': input.consume(kj::StringPtr("false")); output.setBoolean(false); break; case 't': input.consume(kj::StringPtr("true")); output.setBoolean(true); break; case '"': parseString(output); break; case '[': parseArray(output); break; case '{': parseObject(output); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': parseNumber(output); break; default: KJ_FAIL_REQUIRE("Unexpected input in JSON message."); } } void parseNumber(JsonValue::Builder& output) { output.setNumber(consumeNumber().parseAs()); } void parseString(JsonValue::Builder& output) { output.setString(consumeQuotedString()); } void parseArray(JsonValue::Builder& output) { // TODO(perf): Using orphans leaves holes in the message. It's expected // that a JsonValue is used for interop, and won't be sent or written as a // Cap'n Proto message. This also applies to parseObject below. kj::Vector> values; auto orphanage = Orphanage::getForMessageContaining(output); bool expectComma = false; input.consume('['); KJ_REQUIRE(++nestingDepth <= maxNestingDepth, "JSON message nested too deeply."); KJ_DEFER(--nestingDepth); while (input.consumeWhitespace(), input.nextChar() != ']') { auto orphan = orphanage.newOrphan(); auto builder = orphan.get(); if (expectComma) { input.consumeWhitespace(); input.consume(','); input.consumeWhitespace(); } parseValue(builder); values.add(kj::mv(orphan)); expectComma = true; } output.initArray(values.size()); auto array = output.getArray(); for (auto i : kj::indices(values)) { array.adoptWithCaveats(i, kj::mv(values[i])); } input.consume(']'); } void parseObject(JsonValue::Builder& output) { kj::Vector> fields; auto orphanage = Orphanage::getForMessageContaining(output); bool expectComma = false; input.consume('{'); KJ_REQUIRE(++nestingDepth <= maxNestingDepth, "JSON message nested too deeply."); KJ_DEFER(--nestingDepth); while (input.consumeWhitespace(), input.nextChar() != '}') { auto orphan = orphanage.newOrphan(); auto builder = orphan.get(); if (expectComma) { input.consumeWhitespace(); input.consume(','); input.consumeWhitespace(); } builder.setName(consumeQuotedString()); input.consumeWhitespace(); input.consume(':'); input.consumeWhitespace(); auto valueBuilder = builder.getValue(); parseValue(valueBuilder); fields.add(kj::mv(orphan)); expectComma = true; } output.initObject(fields.size()); auto object = output.getObject(); for (auto i : kj::indices(fields)) { object.adoptWithCaveats(i, kj::mv(fields[i])); } input.consume('}'); } bool inputExhausted() { return input.exhausted(); } private: kj::String consumeQuotedString() { input.consume('"'); // TODO(perf): Avoid copy / alloc if no escapes encountered. // TODO(perf): Get statistics on string size and preallocate? kj::Vector decoded; do { auto stringValue = input.consumeWhile([](const char chr) { return chr != '"' && chr != '\\'; }); decoded.addAll(stringValue); if (input.nextChar() == '\\') { // handle escapes. input.advance(); switch(input.nextChar()) { case '"' : decoded.add('"' ); input.advance(); break; case '\\': decoded.add('\\'); input.advance(); break; case '/' : decoded.add('/' ); input.advance(); break; case 'b' : decoded.add('\b'); input.advance(); break; case 'f' : decoded.add('\f'); input.advance(); break; case 'n' : decoded.add('\n'); input.advance(); break; case 'r' : decoded.add('\r'); input.advance(); break; case 't' : decoded.add('\t'); input.advance(); break; case 'u' : input.consume('u'); unescapeAndAppend(input.consume(size_t(4)), decoded); break; default: KJ_FAIL_REQUIRE("Invalid escape in JSON string."); break; } } } while(input.nextChar() != '"'); input.consume('"'); decoded.add('\0'); // TODO(perf): This copy can be eliminated, but I can't find the kj::wayToDoIt(); return kj::String(decoded.releaseAsArray()); } kj::String consumeNumber() { auto numArrayPtr = input.consumeCustom([](Input& input) { input.tryConsume('-'); if (!input.tryConsume('0')) { input.consumeOne([](char c) { return '1' <= c && c <= '9'; }); input.consumeWhile([](char c) { return '0' <= c && c <= '9'; }); } if (input.tryConsume('.')) { input.consumeWhile([](char c) { return '0' <= c && c <= '9'; }); } if (input.tryConsume('e') || input.tryConsume('E')) { input.tryConsume('+') || input.tryConsume('-'); input.consumeWhile([](char c) { return '0' <= c && c <= '9'; }); } }); KJ_REQUIRE(numArrayPtr.size() > 0, "Expected number in JSON input."); kj::Vector number; number.addAll(numArrayPtr); number.add('\0'); return kj::String(number.releaseAsArray()); } // TODO(someday): This "interface" is ugly, and won't work if/when surrogates are handled. void unescapeAndAppend(kj::ArrayPtr hex, kj::Vector& target) { KJ_REQUIRE(hex.size() == 4); int codePoint = 0; for (int i = 0; i < 4; ++i) { char c = hex[i]; codePoint <<= 4; if ('0' <= c && c <= '9') { codePoint |= c - '0'; } else if ('a' <= c && c <= 'f') { codePoint |= c - 'a' + 10; } else if ('A' <= c && c <= 'F') { codePoint |= c - 'A' + 10; } else { KJ_FAIL_REQUIRE("Invalid hex digit in unicode escape.", c); } } if (codePoint < 128) { target.add(0x7f & static_cast(codePoint)); } else { // TODO(perf): This is sorta malloc-heavy... char16_t u = codePoint; target.addAll(kj::decodeUtf16(kj::arrayPtr(&u, 1))); } } const size_t maxNestingDepth; Input input; size_t nestingDepth; }; // class Parser } // namespace void JsonCodec::decodeRaw(kj::ArrayPtr input, JsonValue::Builder output) const { Parser parser(impl->maxNestingDepth, input); parser.parseValue(output); KJ_REQUIRE(parser.inputExhausted(), "Input remains after parsing JSON."); } // ----------------------------------------------------------------------------- Orphan JsonCodec::HandlerBase::decodeBase( const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const { KJ_FAIL_ASSERT("JSON decoder handler type / value type mismatch"); } void JsonCodec::HandlerBase::decodeStructBase( const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const { KJ_FAIL_ASSERT("JSON decoder handler type / value type mismatch"); } void JsonCodec::addTypeHandlerImpl(Type type, HandlerBase& handler) { impl->typeHandlers.upsert(type, &handler, [](HandlerBase*& existing, HandlerBase* replacement) { KJ_REQUIRE(existing == replacement, "type already has a different registered handler"); }); } void JsonCodec::addFieldHandlerImpl(StructSchema::Field field, Type type, HandlerBase& handler) { KJ_REQUIRE(type == field.getType(), "handler type did not match field type for addFieldHandler()"); impl->fieldHandlers.upsert(field, &handler, [](HandlerBase*& existing, HandlerBase* replacement) { KJ_REQUIRE(existing == replacement, "field already has a different registered handler"); }); } // ======================================================================================= static constexpr uint64_t JSON_NAME_ANNOTATION_ID = 0xfa5b1fd61c2e7c3dull; static constexpr uint64_t JSON_FLATTEN_ANNOTATION_ID = 0x82d3e852af0336bfull; static constexpr uint64_t JSON_DISCRIMINATOR_ANNOTATION_ID = 0xcfa794e8d19a0162ull; static constexpr uint64_t JSON_BASE64_ANNOTATION_ID = 0xd7d879450a253e4bull; static constexpr uint64_t JSON_HEX_ANNOTATION_ID = 0xf061e22f0ae5c7b5ull; class JsonCodec::Base64Handler final: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, capnp::Data::Reader input, JsonValue::Builder output) const { output.setString(kj::encodeBase64(input)); } Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const { return orphanage.newOrphanCopy(capnp::Data::Reader(kj::decodeBase64(input.getString()))); } }; class JsonCodec::HexHandler final: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, capnp::Data::Reader input, JsonValue::Builder output) const { output.setString(kj::encodeHex(input)); } Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const { return orphanage.newOrphanCopy(capnp::Data::Reader(kj::decodeHex(input.getString()))); } }; class JsonCodec::AnnotatedHandler final: public JsonCodec::Handler { public: AnnotatedHandler(JsonCodec& codec, StructSchema schema, kj::Maybe discriminator, kj::Maybe unionDeclName, kj::Vector& dependencies) : schema(schema) { auto schemaProto = schema.getProto(); auto typeName = schemaProto.getDisplayName(); if (discriminator == nullptr) { // There are two cases of unions: // * Named unions, which are special cases of named groups. In this case, the union may be // annotated by annotating the field. In this case, we receive a non-null `discriminator` // as a constructor parameter, and schemaProto.getAnnotations() must be empty because // it's not possible to annotate a group's type (because the type is anonymous). // * Unnamed unions, of which there can only be one in any particular scope. In this case, // the parent struct type itself is annotated. // So if we received `null` as the constructor parameter, check for annotations on the struct // type. for (auto anno: schemaProto.getAnnotations()) { switch (anno.getId()) { case JSON_DISCRIMINATOR_ANNOTATION_ID: discriminator = anno.getValue().getStruct().getAs(); break; } } } KJ_IF_MAYBE(d, discriminator) { if (d->hasName()) { unionTagName = d->getName(); } else { unionTagName = unionDeclName; } KJ_IF_MAYBE(u, unionTagName) { fieldsByName.insert(*u, FieldNameInfo { FieldNameInfo::UNION_TAG, 0, 0, nullptr }); } if (d->hasValueName()) { fieldsByName.insert(d->getValueName(), FieldNameInfo { FieldNameInfo::UNION_VALUE, 0, 0, nullptr }); } } discriminantOffset = schemaProto.getStruct().getDiscriminantOffset(); fields = KJ_MAP(field, schema.getFields()) { auto fieldProto = field.getProto(); auto type = field.getType(); auto fieldName = fieldProto.getName(); FieldNameInfo nameInfo; nameInfo.index = field.getIndex(); nameInfo.type = FieldNameInfo::NORMAL; nameInfo.prefixLength = 0; FieldInfo info; info.name = fieldName; kj::Maybe subDiscriminator; bool flattened = false; for (auto anno: field.getProto().getAnnotations()) { switch (anno.getId()) { case JSON_NAME_ANNOTATION_ID: info.name = anno.getValue().getText(); break; case JSON_FLATTEN_ANNOTATION_ID: KJ_REQUIRE(type.isStruct(), "only struct types can be flattened", fieldName, typeName); flattened = true; info.prefix = anno.getValue().getStruct().getAs().getPrefix(); break; case JSON_DISCRIMINATOR_ANNOTATION_ID: KJ_REQUIRE(fieldProto.isGroup(), "only unions can have discriminator"); subDiscriminator = anno.getValue().getStruct().getAs(); break; case JSON_BASE64_ANNOTATION_ID: { KJ_REQUIRE(field.getType().isData(), "only Data can be marked for base64 encoding"); static Base64Handler handler; codec.addFieldHandler(field, handler); break; } case JSON_HEX_ANNOTATION_ID: { KJ_REQUIRE(field.getType().isData(), "only Data can be marked for hex encoding"); static HexHandler handler; codec.addFieldHandler(field, handler); break; } } } if (fieldProto.isGroup()) { // Load group type handler now, even if not flattened, so that we can pass its // `subDiscriminator`. kj::Maybe subFieldName; if (flattened) { // If the group was flattened, then we allow its field name to be used as the // discriminator name, so that the discriminator doesn't have to explicitly specify a // name. subFieldName = fieldName; } auto& subHandler = codec.loadAnnotatedHandler( type.asStruct(), subDiscriminator, subFieldName, dependencies); if (flattened) { info.flattenHandler = subHandler; } } else if (type.isStruct()) { if (flattened) { info.flattenHandler = codec.loadAnnotatedHandler( type.asStruct(), nullptr, nullptr, dependencies); } } bool isUnionMember = fieldProto.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; KJ_IF_MAYBE(fh, info.flattenHandler) { // Set up fieldsByName for each of the child's fields. for (auto& entry: fh->fieldsByName) { kj::StringPtr flattenedName; kj::String ownName; if (info.prefix.size() > 0) { ownName = kj::str(info.prefix, entry.key); flattenedName = ownName; } else { flattenedName = entry.key; } fieldsByName.upsert(flattenedName, FieldNameInfo { isUnionMember ? FieldNameInfo::FLATTENED_FROM_UNION : FieldNameInfo::FLATTENED, field.getIndex(), (uint)info.prefix.size(), kj::mv(ownName) }, [&](FieldNameInfo& existing, FieldNameInfo&& replacement) { KJ_REQUIRE(existing.type == FieldNameInfo::FLATTENED_FROM_UNION && replacement.type == FieldNameInfo::FLATTENED_FROM_UNION, "flattened members have the same name and are not mutually exclusive"); }); } } info.nameForDiscriminant = info.name; if (!flattened) { bool isUnionWithValueName = false; if (isUnionMember) { KJ_IF_MAYBE(d, discriminator) { if (d->hasValueName()) { info.name = d->getValueName(); isUnionWithValueName = true; } } } if (!isUnionWithValueName) { fieldsByName.insert(info.name, kj::mv(nameInfo)); } } if (isUnionMember) { unionTagValues.insert(info.nameForDiscriminant, field); } // Look for dependencies that we need to add. while (type.isList()) type = type.asList().getElementType(); if (codec.impl->typeHandlers.find(type) == nullptr) { switch (type.which()) { case schema::Type::STRUCT: dependencies.add(type.asStruct()); break; case schema::Type::ENUM: dependencies.add(type.asEnum()); break; case schema::Type::INTERFACE: dependencies.add(type.asInterface()); break; default: break; } } return info; }; } const StructSchema schema; void encode(const JsonCodec& codec, DynamicStruct::Reader input, JsonValue::Builder output) const override { kj::Vector flattenedFields; gatherForEncode(codec, input, nullptr, nullptr, flattenedFields); auto outs = output.initObject(flattenedFields.size()); for (auto i: kj::indices(flattenedFields)) { auto& in = flattenedFields[i]; auto out = outs[i]; out.setName(in.name); KJ_SWITCH_ONEOF(in.type) { KJ_CASE_ONEOF(type, Type) { codec.encode(in.value, type, out.initValue()); } KJ_CASE_ONEOF(field, StructSchema::Field) { codec.encodeField(field, in.value, out.initValue()); } } } } void decode(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const override { KJ_REQUIRE(input.isObject()); kj::HashSet unionsSeen; kj::Vector retries; for (auto field: input.getObject()) { if (!decodeField(codec, field.getName(), field.getValue(), output, unionsSeen)) { retries.add(field); } } while (!retries.empty()) { auto retriesCopy = kj::mv(retries); KJ_ASSERT(retries.empty()); for (auto field: retriesCopy) { if (!decodeField(codec, field.getName(), field.getValue(), output, unionsSeen)) { retries.add(field); } } if (retries.size() == retriesCopy.size()) { // We made no progress in this iteration. Give up on the remaining fields. break; } } } private: struct FieldInfo { kj::StringPtr name; kj::StringPtr nameForDiscriminant; kj::Maybe flattenHandler; kj::StringPtr prefix; }; kj::Array fields; // Maps field index -> info about the field struct FieldNameInfo { enum { NORMAL, // This is a normal field with the given `index`. FLATTENED, // This is a field of a flattened inner struct or group (that is not in a union). `index` // is the field index of the particular struct/group field. UNION_TAG, // The parent struct is a flattened union, and this field is the discriminant tag. It is a // string field whose name determines the union type. `index` is not used. FLATTENED_FROM_UNION, // The parent struct is a flattened union, and some of the union's members are flattened // structs or groups, and this field is possibly a member of one or more of them. `index` // is not used, because it's possible that the same field name appears in multiple variants. // Instead, the parser must find the union tag, and then can descend and attempt to parse // the field in the context of whichever variant is selected. UNION_VALUE // This field is the value of a discriminated union that has `valueName` set. } type; uint index; // For `NORMAL` and `FLATTENED`, the index of the field in schema.getFields(). uint prefixLength; kj::String ownName; }; kj::HashMap fieldsByName; // Maps JSON names to info needed to parse them. kj::HashMap unionTagValues; // If the parent struct is a flattened union, it has a tag field which is a string with one of // these values. The map maps to the union member to set. kj::Maybe unionTagName; // If the parent struct is a flattened union, the name of the "tag" field. uint discriminantOffset; // Shortcut for schema.getProto().getStruct().getDiscriminantOffset(), used in a hack to identify // which unions have been seen. struct FlattenedField { kj::String ownName; kj::StringPtr name; kj::OneOf type; DynamicValue::Reader value; FlattenedField(kj::StringPtr prefix, kj::StringPtr name, kj::OneOf type, DynamicValue::Reader value) : ownName(prefix.size() > 0 ? kj::str(prefix, name) : nullptr), name(prefix.size() > 0 ? ownName : name), type(type), value(value) {} }; void gatherForEncode(const JsonCodec& codec, DynamicValue::Reader input, kj::StringPtr prefix, kj::StringPtr morePrefix, kj::Vector& flattenedFields) const { kj::String ownPrefix; if (morePrefix.size() > 0) { if (prefix.size() > 0) { ownPrefix = kj::str(prefix, morePrefix); prefix = ownPrefix; } else { prefix = morePrefix; } } auto reader = input.as(); auto schema = reader.getSchema(); for (auto field: schema.getNonUnionFields()) { auto& info = fields[field.getIndex()]; if (!reader.has(field, codec.impl->hasMode)) { // skip } else KJ_IF_MAYBE(handler, info.flattenHandler) { handler->gatherForEncode(codec, reader.get(field), prefix, info.prefix, flattenedFields); } else { flattenedFields.add(FlattenedField { prefix, info.name, field, reader.get(field) }); } } KJ_IF_MAYBE(which, reader.which()) { auto& info = fields[which->getIndex()]; KJ_IF_MAYBE(tag, unionTagName) { flattenedFields.add(FlattenedField { prefix, *tag, Type(schema::Type::TEXT), Text::Reader(info.nameForDiscriminant) }); } KJ_IF_MAYBE(handler, info.flattenHandler) { handler->gatherForEncode(codec, reader.get(*which), prefix, info.prefix, flattenedFields); } else { auto type = which->getType(); if (type.which() == schema::Type::VOID && unionTagName != nullptr) { // When we have an explicit union discriminant, we don't need to encode void fields. } else { flattenedFields.add(FlattenedField { prefix, info.name, *which, reader.get(*which) }); } } } } bool decodeField(const JsonCodec& codec, kj::StringPtr name, JsonValue::Reader value, DynamicStruct::Builder output, kj::HashSet& unionsSeen) const { KJ_ASSERT(output.getSchema() == schema); KJ_IF_MAYBE(info, fieldsByName.find(name)) { switch (info->type) { case FieldNameInfo::NORMAL: { auto field = output.getSchema().getFields()[info->index]; codec.decodeField(field, value, Orphanage::getForMessageContaining(output), output); return true; } case FieldNameInfo::FLATTENED: return KJ_ASSERT_NONNULL(fields[info->index].flattenHandler) .decodeField(codec, name.slice(info->prefixLength), value, output.get(output.getSchema().getFields()[info->index]).as(), unionsSeen); case FieldNameInfo::UNION_TAG: { KJ_REQUIRE(value.isString(), "Expected string value."); // Mark that we've seen a union tag for this struct. const void* ptr = getUnionInstanceIdentifier(output); KJ_IF_MAYBE(field, unionTagValues.find(value.getString())) { // clear() has the side-effect of activating this member of the union, without // allocating any objects. output.clear(*field); unionsSeen.insert(ptr); } return true; } case FieldNameInfo::FLATTENED_FROM_UNION: { const void* ptr = getUnionInstanceIdentifier(output); if (unionsSeen.contains(ptr)) { auto variant = KJ_ASSERT_NONNULL(output.which()); return KJ_ASSERT_NONNULL(fields[variant.getIndex()].flattenHandler) .decodeField(codec, name.slice(info->prefixLength), value, output.get(variant).as(), unionsSeen); } else { // We haven't seen the union tag yet, so we can't parse this field yet. Try again later. return false; } } case FieldNameInfo::UNION_VALUE: { const void* ptr = getUnionInstanceIdentifier(output); if (unionsSeen.contains(ptr)) { auto variant = KJ_ASSERT_NONNULL(output.which()); codec.decodeField(variant, value, Orphanage::getForMessageContaining(output), output); return true; } else { // We haven't seen the union tag yet, so we can't parse this field yet. Try again later. return false; } } } KJ_UNREACHABLE; } else { // Ignore undefined field -- unless the flag is set to reject them. KJ_REQUIRE(!codec.impl->rejectUnknownFields, "Unknown field", name); return true; } } const void* getUnionInstanceIdentifier(DynamicStruct::Builder obj) const { // Gets a value uniquely identifying an instance of a union. // HACK: We return a pointer to the union's discriminant within the underlying buffer. return reinterpret_cast( AnyStruct::Reader(obj.asReader()).getDataSection().begin()) + discriminantOffset; } }; class JsonCodec::AnnotatedEnumHandler final: public JsonCodec::Handler { public: AnnotatedEnumHandler(EnumSchema schema): schema(schema) { auto enumerants = schema.getEnumerants(); auto builder = kj::heapArrayBuilder(enumerants.size()); for (auto e: enumerants) { auto proto = e.getProto(); kj::StringPtr name = proto.getName(); for (auto anno: proto.getAnnotations()) { switch (anno.getId()) { case JSON_NAME_ANNOTATION_ID: name = anno.getValue().getText(); break; } } builder.add(name); nameToValue.insert(name, e.getIndex()); } valueToName = builder.finish(); } void encode(const JsonCodec& codec, DynamicEnum input, JsonValue::Builder output) const override { KJ_IF_MAYBE(e, input.getEnumerant()) { KJ_ASSERT(e->getIndex() < valueToName.size()); output.setString(valueToName[e->getIndex()]); } else { output.setNumber(input.getRaw()); } } DynamicEnum decode(const JsonCodec& codec, JsonValue::Reader input) const override { if (input.isNumber()) { return DynamicEnum(schema, static_cast(input.getNumber())); } else { uint16_t val = KJ_REQUIRE_NONNULL(nameToValue.find(input.getString()), "invalid enum value", input.getString()); return DynamicEnum(schema.getEnumerants()[val]); } } private: EnumSchema schema; kj::Array valueToName; kj::HashMap nameToValue; }; class JsonCodec::JsonValueHandler final: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, DynamicStruct::Reader input, JsonValue::Builder output) const override { #if _MSC_VER && !defined(__clang__) // TODO(msvc): Hack to work around missing AnyStruct::Builder constructor on MSVC. rawCopy(input, toDynamic(output)); #else rawCopy(input, kj::mv(output)); #endif } void decode(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const override { rawCopy(input, kj::mv(output)); } private: void rawCopy(AnyStruct::Reader input, AnyStruct::Builder output) const { // HACK: Manually copy using AnyStruct, so that if JsonValue's definition changes, this code // doesn't need to be updated. However, note that if JsonValue ever adds new fields that // change its size, and the input struct is a newer version than the output, we may lose // the new fields. Technically the "correct" thing to do would be to allocate the output // struct to be exactly the same size as the input, but JsonCodec's Handler interface is // not designed to allow that -- it passes in an already-allocated builder. Oops. auto dataIn = input.getDataSection(); auto dataOut = output.getDataSection(); memcpy(dataOut.begin(), dataIn.begin(), kj::min(dataOut.size(), dataIn.size())); auto ptrIn = input.getPointerSection(); auto ptrOut = output.getPointerSection(); for (auto i: kj::zeroTo(kj::min(ptrIn.size(), ptrOut.size()))) { ptrOut[i].set(ptrIn[i]); } } }; JsonCodec::AnnotatedHandler& JsonCodec::loadAnnotatedHandler( StructSchema schema, kj::Maybe discriminator, kj::Maybe unionDeclName, kj::Vector& dependencies) { auto& entry = impl->annotatedHandlers.upsert(schema, nullptr, [&](kj::Maybe>& existing, auto dummy) { KJ_ASSERT(existing != nullptr, "cyclic JSON flattening detected", schema.getProto().getDisplayName()); }); KJ_IF_MAYBE(v, entry.value) { // Already exists. return **v; } else { // Not seen before. auto newHandler = kj::heap( *this, schema, discriminator, unionDeclName, dependencies); auto& result = *newHandler; // Map may have changed, so we have to look up again. KJ_ASSERT_NONNULL(impl->annotatedHandlers.find(schema)) = kj::mv(newHandler); addTypeHandler(schema, result); return result; }; } void JsonCodec::handleByAnnotation(Schema schema) { switch (schema.getProto().which()) { case schema::Node::STRUCT: { if (schema.getProto().getId() == capnp::typeId()) { // Special handler for JsonValue. static JsonValueHandler GLOBAL_HANDLER; addTypeHandler(schema.asStruct(), GLOBAL_HANDLER); } else { kj::Vector dependencies; loadAnnotatedHandler(schema.asStruct(), nullptr, nullptr, dependencies); for (auto dep: dependencies) { handleByAnnotation(dep); } } break; } case schema::Node::ENUM: { auto enumSchema = schema.asEnum(); impl->annotatedEnumHandlers.findOrCreate(enumSchema, [&]() { auto handler = kj::heap(enumSchema); addTypeHandler(enumSchema, *handler); return kj::HashMap>::Entry { enumSchema, kj::mv(handler) }; }); break; } default: break; } } } // namespace capnp capnproto-c++-1.1.0/src/capnp/compat/json.h0000644000175000017500000005722114527152321021250 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include CAPNP_BEGIN_HEADER namespace capnp { typedef json::Value JsonValue; // For backwards-compatibility. // // TODO(cleanup): Consider replacing all uses of JsonValue with json::Value? class JsonCodec { // Flexible class for encoding Cap'n Proto types as JSON, and decoding JSON back to Cap'n Proto. // // Typical usage: // // JsonCodec json; // // // encode // kj::String encoded = json.encode(someStructReader); // // // decode // json.decode(encoded, someStructBuilder); // // Advanced users can do fancy things like override the way certain types or fields are // represented in JSON by registering handlers. See the unit test for an example. // // Notes: // - When encoding, all primitive fields are always encoded, even if default-valued. Pointer // fields are only encoded if they are non-null. // - 64-bit integers are encoded as strings, since JSON "numbers" are double-precision floating // points which cannot store a 64-bit integer without losing data. // - NaNs and infinite floating point numbers are not allowed by the JSON spec, and so are encoded // as strings. // - Data is encoded as an array of numbers in the range [0,255]. You probably want to register // a handler that does something better, like maybe base64 encoding, but there are a zillion // different ways people do this. // - Encoding/decoding capabilities and AnyPointers requires registering a Handler, since there's // no obvious default behavior. // - When decoding, fields with unknown names are ignored by default to allow schema evolution. public: JsonCodec(); ~JsonCodec() noexcept(false); // --------------------------------------------------------------------------- // standard API void setPrettyPrint(bool enabled); // Enable to insert newlines, indentation, and other extra spacing into the output. The default // is to use minimal whitespace. void setMaxNestingDepth(size_t maxNestingDepth); // Set maximum nesting depth when decoding JSON to prevent highly nested input from overflowing // the call stack. The default is 64. void setHasMode(HasMode mode); // Normally, primitive field values are always included even if they are equal to the default // value (HasMode::NON_NULL -- only null pointers are omitted). You can use // setHasMode(HasMode::NON_DEFAULT) to specify that default-valued primitive fields should be // omitted as well. void setRejectUnknownFields(bool enable); // Choose whether decoding JSON with unknown fields should produce an error. You may trade // allowing schema evolution against a guarantee that all data is preserved when decoding JSON // by toggling this option. The default is to ignore unknown fields. template kj::String encode(T&& value) const; // Encode any Cap'n Proto value to JSON, including primitives and // Dynamic{Enum,Struct,List,Capability}, but not DynamicValue (see below). kj::String encode(DynamicValue::Reader value, Type type) const; // Encode a DynamicValue to JSON. `type` is needed because `DynamicValue` itself does // not distinguish between e.g. int32 and int64, which in JSON are handled differently. Most // of the time, though, you can use the single-argument templated version of `encode()` instead. void decode(kj::ArrayPtr input, DynamicStruct::Builder output) const; // Decode JSON text directly into a struct builder. This only works for structs since lists // need to be allocated with the correct size in advance. // // (Remember that any Cap'n Proto struct reader type can be implicitly cast to // DynamicStruct::Reader.) template Orphan decode(kj::ArrayPtr input, Orphanage orphanage) const; // Decode JSON text to any Cap'n Proto object (pointer value), allocated using the given // orphanage. T must be specified explicitly and cannot be dynamic, e.g.: // // Orphan orphan = json.decode(text, orphanage); template ReaderFor decode(kj::ArrayPtr input) const; // Decode JSON text into a primitive or capability value. T must be specified explicitly and // cannot be dynamic, e.g.: // // uint32_t n = json.decode(text); Orphan decode(kj::ArrayPtr input, Type type, Orphanage orphanage) const; Orphan decode( kj::ArrayPtr input, ListSchema type, Orphanage orphanage) const; Orphan decode( kj::ArrayPtr input, StructSchema type, Orphanage orphanage) const; DynamicCapability::Client decode(kj::ArrayPtr input, InterfaceSchema type) const; DynamicEnum decode(kj::ArrayPtr input, EnumSchema type) const; // Decode to a dynamic value, specifying the type schema. // --------------------------------------------------------------------------- // layered API // // You can separate text <-> JsonValue from JsonValue <-> T. These are particularly useful // for calling from Handler implementations. kj::String encodeRaw(JsonValue::Reader value) const; void decodeRaw(kj::ArrayPtr input, JsonValue::Builder output) const; // Translate JsonValue <-> text. template void encode(T&& value, JsonValue::Builder output) const; void encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const; void decode(JsonValue::Reader input, DynamicStruct::Builder output) const; template Orphan decode(JsonValue::Reader input, Orphanage orphanage) const; template ReaderFor decode(JsonValue::Reader input) const; Orphan decode(JsonValue::Reader input, Type type, Orphanage orphanage) const; Orphan decode(JsonValue::Reader input, ListSchema type, Orphanage orphanage) const; Orphan decode( JsonValue::Reader input, StructSchema type, Orphanage orphanage) const; DynamicCapability::Client decode(JsonValue::Reader input, InterfaceSchema type) const; DynamicEnum decode(JsonValue::Reader input, EnumSchema type) const; // --------------------------------------------------------------------------- // specializing particular types template ()> class Handler; // Implement this interface to specify a special encoding for a particular type or field. // // The templates are a bit ugly, but subclasses of this type essentially implement two methods, // one to encode values of this type and one to decode values of this type. `encode()` is simple: // // void encode(const JsonCodec& codec, ReaderFor input, JsonValue::Builder output) const; // // `decode()` is a bit trickier. When T is a struct (including DynamicStruct), it is: // // void decode(const JsonCodec& codec, JsonValue::Reader input, BuilderFor output) const; // // However, when T is a primitive, decode() is: // // T decode(const JsonCodec& codec, JsonValue::Reader input) const; // // Or when T is any non-struct object (list, blob), decode() is: // // Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const; // // Or when T is an interface: // // T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const; // // Additionally, when T is a struct you can *optionally* also implement the orphan-returning form // of decode(), but it will only be called when the struct would be allocated as an individual // object, not as part of a list. This allows you to return "nullptr" in these cases to say that // the pointer value should be null. This does not apply to list elements because struct list // elements cannot ever be null (since Cap'n Proto encodes struct lists as a flat list rather // than list-of-pointers). template void addTypeHandler(Handler& handler); void addTypeHandler(Type type, Handler& handler); void addTypeHandler(EnumSchema type, Handler& handler); void addTypeHandler(StructSchema type, Handler& handler); void addTypeHandler(ListSchema type, Handler& handler); void addTypeHandler(InterfaceSchema type, Handler& handler); // Arrange that whenever the type T appears in the message, your handler will be used to // encode/decode it. // // Note that if you register a handler for a capability type, it will also apply to subtypes. // Thus Handler handles all capabilities. template void addFieldHandler(StructSchema::Field field, Handler& handler); // Matches only the specific field. T can be a dynamic type. T must match the field's type. void handleByAnnotation(Schema schema); template void handleByAnnotation(); // Inspects the given type (as specified by type parameter or dynamic schema) and all its // dependencies looking for JSON annotations (see json.capnp), building and registering Handlers // based on these annotations. // // If you'd like to use annotations to control JSON, you must call these functions before you // start using the codec. They are not loaded "on demand" because that would require mutex // locking. // --------------------------------------------------------------------------- // Hack to support string literal parameters template auto decode(const char (&input)[size], Params&&... params) const -> decltype(decode(kj::arrayPtr(input, size), kj::fwd(params)...)) { return decode(kj::arrayPtr(input, size - 1), kj::fwd(params)...); } template auto decodeRaw(const char (&input)[size], Params&&... params) const -> decltype(decodeRaw(kj::arrayPtr(input, size), kj::fwd(params)...)) { return decodeRaw(kj::arrayPtr(input, size - 1), kj::fwd(params)...); } private: class HandlerBase; class AnnotatedHandler; class AnnotatedEnumHandler; class Base64Handler; class HexHandler; class JsonValueHandler; struct Impl; kj::Own impl; void encodeField(StructSchema::Field field, DynamicValue::Reader input, JsonValue::Builder output) const; Orphan decodeArray(List::Reader input, ListSchema type, Orphanage orphanage) const; void decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const; void decodeField(StructSchema::Field fieldSchema, JsonValue::Reader fieldValue, Orphanage orphanage, DynamicStruct::Builder output) const; void addTypeHandlerImpl(Type type, HandlerBase& handler); void addFieldHandlerImpl(StructSchema::Field field, Type type, HandlerBase& handler); AnnotatedHandler& loadAnnotatedHandler( StructSchema schema, kj::Maybe discriminator, kj::Maybe unionDeclName, kj::Vector& dependencies); }; // ======================================================================================= // inline implementation details template struct EncodeImpl; template kj::String JsonCodec::encode(T&& value) const { Type type = Type::from(value); typedef FromAny> Base; return encode(DynamicValue::Reader(ReaderFor(kj::fwd(value))), type); } template inline Orphan JsonCodec::decode(kj::ArrayPtr input, Orphanage orphanage) const { return decode(input, Type::from(), orphanage).template releaseAs(); } template inline ReaderFor JsonCodec::decode(kj::ArrayPtr input) const { static_assert(style() == Style::PRIMITIVE || style() == Style::CAPABILITY, "must specify an orphanage to decode an object type"); return decode(input, Type::from(), Orphanage()).getReader().template as(); } inline Orphan JsonCodec::decode( kj::ArrayPtr input, ListSchema type, Orphanage orphanage) const { return decode(input, Type(type), orphanage).releaseAs(); } inline Orphan JsonCodec::decode( kj::ArrayPtr input, StructSchema type, Orphanage orphanage) const { return decode(input, Type(type), orphanage).releaseAs(); } inline DynamicCapability::Client JsonCodec::decode( kj::ArrayPtr input, InterfaceSchema type) const { return decode(input, Type(type), Orphanage()).getReader().as(); } inline DynamicEnum JsonCodec::decode(kj::ArrayPtr input, EnumSchema type) const { return decode(input, Type(type), Orphanage()).getReader().as(); } // ----------------------------------------------------------------------------- template void JsonCodec::encode(T&& value, JsonValue::Builder output) const { typedef FromAny> Base; encode(DynamicValue::Reader(ReaderFor(kj::fwd(value))), Type::from(), output); } template <> inline void JsonCodec::encode( DynamicStruct::Reader&& value, JsonValue::Builder output) const { encode(DynamicValue::Reader(value), value.getSchema(), output); } template inline Orphan JsonCodec::decode(JsonValue::Reader input, Orphanage orphanage) const { return decode(input, Type::from(), orphanage).template releaseAs(); } template inline ReaderFor JsonCodec::decode(JsonValue::Reader input) const { static_assert(style() == Style::PRIMITIVE || style() == Style::CAPABILITY, "must specify an orphanage to decode an object type"); return decode(input, Type::from(), Orphanage()).getReader().template as(); } inline Orphan JsonCodec::decode( JsonValue::Reader input, ListSchema type, Orphanage orphanage) const { return decode(input, Type(type), orphanage).releaseAs(); } inline Orphan JsonCodec::decode( JsonValue::Reader input, StructSchema type, Orphanage orphanage) const { return decode(input, Type(type), orphanage).releaseAs(); } inline DynamicCapability::Client JsonCodec::decode( JsonValue::Reader input, InterfaceSchema type) const { return decode(input, Type(type), Orphanage()).getReader().as(); } inline DynamicEnum JsonCodec::decode(JsonValue::Reader input, EnumSchema type) const { return decode(input, Type(type), Orphanage()).getReader().as(); } // ----------------------------------------------------------------------------- class JsonCodec::HandlerBase { // Internal helper; ignore. public: virtual void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const = 0; virtual Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const; virtual void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const; }; template class JsonCodec::Handler: private JsonCodec::HandlerBase { public: virtual void encode(const JsonCodec& codec, ReaderFor input, JsonValue::Builder output) const = 0; virtual Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const = 0; private: void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const override final { encode(codec, input.as(), output); } Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const override final { return decode(codec, input, orphanage); } friend class JsonCodec; }; template class JsonCodec::Handler: private JsonCodec::HandlerBase { public: virtual void encode(const JsonCodec& codec, ReaderFor input, JsonValue::Builder output) const = 0; virtual void decode(const JsonCodec& codec, JsonValue::Reader input, BuilderFor output) const = 0; virtual Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const { // If subclass does not override, fall back to regular version. auto result = orphanage.newOrphan(); decode(codec, input, result.get()); return result; } private: void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const override final { encode(codec, input.as(), output); } Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const override final { return decode(codec, input, orphanage); } void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const override final { decode(codec, input, output.as()); } friend class JsonCodec; }; template <> class JsonCodec::Handler: private JsonCodec::HandlerBase { // Almost identical to Style::STRUCT except that we pass the struct type to decode(). public: virtual void encode(const JsonCodec& codec, DynamicStruct::Reader input, JsonValue::Builder output) const = 0; virtual void decode(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const = 0; virtual Orphan decode(const JsonCodec& codec, JsonValue::Reader input, StructSchema type, Orphanage orphanage) const { // If subclass does not override, fall back to regular version. auto result = orphanage.newOrphan(type); decode(codec, input, result.get()); return result; } private: void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const override final { encode(codec, input.as(), output); } Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const override final { return decode(codec, input, type.asStruct(), orphanage); } void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const override final { decode(codec, input, output.as()); } friend class JsonCodec; }; template class JsonCodec::Handler: private JsonCodec::HandlerBase { public: virtual void encode(const JsonCodec& codec, T input, JsonValue::Builder output) const = 0; virtual T decode(const JsonCodec& codec, JsonValue::Reader input) const = 0; private: void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const override final { encode(codec, input.as(), output); } Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const override final { return decode(codec, input); } friend class JsonCodec; }; template class JsonCodec::Handler: private JsonCodec::HandlerBase { public: virtual void encode(const JsonCodec& codec, typename T::Client input, JsonValue::Builder output) const = 0; virtual typename T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const = 0; private: void encodeBase(const JsonCodec& codec, DynamicValue::Reader input, JsonValue::Builder output) const override final { encode(codec, input.as(), output); } Orphan decodeBase(const JsonCodec& codec, JsonValue::Reader input, Type type, Orphanage orphanage) const override final { return orphanage.newOrphanCopy(decode(codec, input)); } friend class JsonCodec; }; template inline void JsonCodec::addTypeHandler(Handler& handler) { addTypeHandlerImpl(Type::from(), handler); } inline void JsonCodec::addTypeHandler(Type type, Handler& handler) { addTypeHandlerImpl(type, handler); } inline void JsonCodec::addTypeHandler(EnumSchema type, Handler& handler) { addTypeHandlerImpl(type, handler); } inline void JsonCodec::addTypeHandler(StructSchema type, Handler& handler) { addTypeHandlerImpl(type, handler); } inline void JsonCodec::addTypeHandler(ListSchema type, Handler& handler) { addTypeHandlerImpl(type, handler); } inline void JsonCodec::addTypeHandler(InterfaceSchema type, Handler& handler) { addTypeHandlerImpl(type, handler); } template inline void JsonCodec::addFieldHandler(StructSchema::Field field, Handler& handler) { addFieldHandlerImpl(field, Type::from(), handler); } template <> void JsonCodec::addTypeHandler(Handler& handler) KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " "try specifying a specific type schema as the first parameter"); template <> void JsonCodec::addTypeHandler(Handler& handler) KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " "try specifying a specific type schema as the first parameter"); template <> void JsonCodec::addTypeHandler(Handler& handler) KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " "try specifying a specific type schema as the first parameter"); template <> void JsonCodec::addTypeHandler(Handler& handler) KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " "try specifying a specific type schema as the first parameter"); template <> void JsonCodec::addTypeHandler(Handler& handler) KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; " "try specifying a specific type schema as the first parameter"); // TODO(someday): Implement support for registering handlers that cover thinsg like "all structs" // or "all lists". Currently you can only target a specific struct or list type. template void JsonCodec::handleByAnnotation() { return handleByAnnotation(Schema::from()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compat/std-iterator.h0000644000175000017500000000357214712011043022707 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once // This exposes IndexingIterator as something compatible with std::iterator so that things like // std::copy work with List::begin/List::end. // Make sure that if this header is before list.h by the user it includes it to make // IndexingIterator visible to avoid brittle header problems. #include "../list.h" #include CAPNP_BEGIN_HEADER namespace std { template struct iterator_traits> { using iterator_category = std::random_access_iterator_tag; using value_type = Element; using difference_type = int; using pointer = Element*; using reference = Element; }; } // namespace std CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/compat/json-test.capnp0000644000175000017500000000654714527152321023104 0ustar00kentonkenton00000000000000# Copyright (c) 2018 Cloudflare, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xc9d405cf4333e4c9; using Json = import "/capnp/compat/json.capnp"; $import "/capnp/c++.capnp".namespace("capnp"); struct TestJsonAnnotations { someField @0 :Text $Json.name("names-can_contain!anything Really"); aGroup :group $Json.flatten() { flatFoo @1 :UInt32; flatBar @2 :Text; flatBaz :group $Json.name("renamed-flatBaz") { hello @3 :Bool; } doubleFlat :group $Json.flatten() { flatQux @4 :Text; } } prefixedGroup :group $Json.flatten(prefix = "pfx.") { foo @5 :Text; bar @6 :UInt32 $Json.name("renamed-bar"); baz :group { hello @7 :Bool; } morePrefix :group $Json.flatten(prefix = "xfp.") { qux @8 :Text; } } aUnion :union $Json.flatten() $Json.discriminator(name = "union-type") { foo :group $Json.flatten() { fooMember @9 :Text; multiMember @10 :UInt32; } bar :group $Json.flatten() $Json.name("renamed-bar") { barMember @11 :UInt32; multiMember @12 :Text; } } dependency @13 :TestJsonAnnotations2; # To test that dependencies are loaded even if not flattened. simpleGroup :group { # To test that group types are loaded even if not flattened. grault @14 :Text $Json.name("renamed-grault"); } enums @15 :List(TestJsonAnnotatedEnum); innerJson @16 :Json.Value; customFieldHandler @17 :Text; testBase64 @18 :Data $Json.base64; testHex @19 :Data $Json.hex; bUnion :union $Json.flatten() $Json.discriminator(valueName = "bValue") { foo @20 :Text; bar @21 :UInt32 $Json.name("renamed-bar"); } externalUnion @22 :TestJsonAnnotations3; unionWithVoid :union $Json.discriminator(name = "type") { intValue @23 :UInt32; voidValue @24 :Void; textValue @25 :Text; } } struct TestJsonAnnotations2 { foo @0 :Text $Json.name("renamed-foo"); cycle @1 :TestJsonAnnotations; } struct TestJsonAnnotations3 $Json.discriminator(name = "type") { union { foo @0 :UInt32; bar @1 :TestFlattenedStruct $Json.flatten(); } } struct TestFlattenedStruct { value @0 :Text; } enum TestJsonAnnotatedEnum { foo @0; bar @1 $Json.name("renamed-bar"); baz @2 $Json.name("renamed-baz"); qux @3; } struct TestBase64Union { union { foo @0 :Data $Json.base64; bar @1 :Text; } } capnproto-c++-1.1.0/src/capnp/compat/json-test.c++0000644000175000017500000012111414712011043022326 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "json.h" #include #include #include #include #include #include namespace capnp { namespace _ { // private namespace { KJ_TEST("basic json encoding") { JsonCodec json; KJ_EXPECT(json.encode(VOID) == "null"); KJ_EXPECT(json.encode(true) == "true"); KJ_EXPECT(json.encode(false) == "false"); KJ_EXPECT(json.encode(123) == "123"); KJ_EXPECT(json.encode(-5.5) == "-5.5"); KJ_EXPECT(json.encode(Text::Reader("foo")) == "\"foo\""); KJ_EXPECT(json.encode(Text::Reader("ab\"cd\\ef\x03")) == "\"ab\\\"cd\\\\ef\\u0003\""); KJ_EXPECT(json.encode(test::TestEnum::CORGE) == "\"corge\""); byte bytes[] = {12, 34, 56}; KJ_EXPECT(json.encode(Data::Reader(bytes, 3)) == "[12,34,56]"); json.setPrettyPrint(true); KJ_EXPECT(json.encode(Data::Reader(bytes, 3)) == "[12, 34, 56]"); } KJ_TEST("raw encoding") { JsonCodec json; auto text = kj::str("{\"field\":\"value\"}"); MallocMessageBuilder message; auto value = message.initRoot(); value.setRaw(text); KJ_EXPECT(json.encodeRaw(value) == text); } const char ALL_TYPES_JSON[] = "{ \"voidField\": null,\n" " \"boolField\": true,\n" " \"int8Field\": -123,\n" " \"int16Field\": -12345,\n" " \"int32Field\": -12345678,\n" " \"int64Field\": \"-123456789012345\",\n" " \"uInt8Field\": 234,\n" " \"uInt16Field\": 45678,\n" " \"uInt32Field\": 3456789012,\n" " \"uInt64Field\": \"12345678901234567890\",\n" " \"float32Field\": 1234.5,\n" " \"float64Field\": -1.23e47,\n" " \"textField\": \"foo\",\n" " \"dataField\": [98, 97, 114],\n" " \"structField\": {\n" " \"voidField\": null,\n" " \"boolField\": true,\n" " \"int8Field\": -12,\n" " \"int16Field\": 3456,\n" " \"int32Field\": -78901234,\n" " \"int64Field\": \"56789012345678\",\n" " \"uInt8Field\": 90,\n" " \"uInt16Field\": 1234,\n" " \"uInt32Field\": 56789012,\n" " \"uInt64Field\": \"345678901234567890\",\n" " \"float32Field\": -1.2499999646475857e-10,\n" " \"float64Field\": 345,\n" " \"textField\": \"baz\",\n" " \"dataField\": [113, 117, 120],\n" " \"structField\": {\n" " \"voidField\": null,\n" " \"boolField\": false,\n" " \"int8Field\": 0,\n" " \"int16Field\": 0,\n" " \"int32Field\": 0,\n" " \"int64Field\": \"0\",\n" " \"uInt8Field\": 0,\n" " \"uInt16Field\": 0,\n" " \"uInt32Field\": 0,\n" " \"uInt64Field\": \"0\",\n" " \"float32Field\": 0,\n" " \"float64Field\": 0,\n" " \"textField\": \"nested\",\n" " \"structField\": {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"really nested\", \"enumField\": \"foo\", \"interfaceField\": null},\n" " \"enumField\": \"foo\",\n" " \"interfaceField\": null },\n" " \"enumField\": \"baz\",\n" " \"interfaceField\": null,\n" " \"voidList\": [null, null, null],\n" " \"boolList\": [false, true, false, true, true],\n" " \"int8List\": [12, -34, -128, 127],\n" " \"int16List\": [1234, -5678, -32768, 32767],\n" " \"int32List\": [12345678, -90123456, -2147483648, 2147483647],\n" " \"int64List\": [\"123456789012345\", \"-678901234567890\", \"-9223372036854775808\", \"9223372036854775807\"],\n" " \"uInt8List\": [12, 34, 0, 255],\n" " \"uInt16List\": [1234, 5678, 0, 65535],\n" " \"uInt32List\": [12345678, 90123456, 0, 4294967295],\n" " \"uInt64List\": [\"123456789012345\", \"678901234567890\", \"0\", \"18446744073709551615\"],\n" " \"float32List\": [0, 1234567, 9.9999999338158125e36, -9.9999999338158125e36, 9.99999991097579e-38, -9.99999991097579e-38],\n" " \"float64List\": [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306],\n" " \"textList\": [\"quux\", \"corge\", \"grault\"],\n" " \"dataList\": [[103, 97, 114, 112, 108, 121], [119, 97, 108, 100, 111], [102, 114, 101, 100]],\n" " \"structList\": [\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 1\", \"enumField\": \"foo\", \"interfaceField\": null},\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 2\", \"enumField\": \"foo\", \"interfaceField\": null},\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"x structlist 3\", \"enumField\": \"foo\", \"interfaceField\": null} ],\n" " \"enumList\": [\"qux\", \"bar\", \"grault\"] },\n" " \"enumField\": \"corge\",\n" " \"interfaceField\": null,\n" " \"voidList\": [null, null, null, null, null, null],\n" " \"boolList\": [true, false, false, true],\n" " \"int8List\": [111, -111],\n" " \"int16List\": [11111, -11111],\n" " \"int32List\": [111111111, -111111111],\n" " \"int64List\": [\"1111111111111111111\", \"-1111111111111111111\"],\n" " \"uInt8List\": [111, 222],\n" " \"uInt16List\": [33333, 44444],\n" " \"uInt32List\": [3333333333],\n" " \"uInt64List\": [\"11111111111111111111\"],\n" " \"float32List\": [5555.5, \"Infinity\", \"-Infinity\", \"NaN\"],\n" " \"float64List\": [7777.75, \"Infinity\", \"-Infinity\", \"NaN\"],\n" " \"textList\": [\"plugh\", \"xyzzy\", \"thud\"],\n" " \"dataList\": [[111, 111, 112, 115], [101, 120, 104, 97, 117, 115, 116, 101, 100], [114, 102, 99, 51, 48, 57, 50]],\n" " \"structList\": [\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 1\", \"enumField\": \"foo\", \"interfaceField\": null},\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 2\", \"enumField\": \"foo\", \"interfaceField\": null},\n" " {\"voidField\": null, \"boolField\": false, \"int8Field\": 0, \"int16Field\": 0, \"int32Field\": 0, \"int64Field\": \"0\", \"uInt8Field\": 0, \"uInt16Field\": 0, \"uInt32Field\": 0, \"uInt64Field\": \"0\", \"float32Field\": 0, \"float64Field\": 0, \"textField\": \"structlist 3\", \"enumField\": \"foo\", \"interfaceField\": null} ],\n" " \"enumList\": [\"foo\", \"garply\"] }"; KJ_TEST("encode all types") { MallocMessageBuilder message; auto root = message.getRoot(); initTestMessage(root); JsonCodec json; json.setPrettyPrint(true); KJ_EXPECT(json.encode(root) == ALL_TYPES_JSON); // Verify that if we strip out the non-string spaces, we get the non-pretty-print version. kj::Vector chars; bool inQuotes = false; for (char c: ALL_TYPES_JSON) { if (c == '\"') inQuotes = !inQuotes; if ((c == '\n' || c == ' ') && !inQuotes) { // skip space } else { chars.add(c); } } kj::String nospaces(chars.releaseAsArray()); json.setPrettyPrint(false); KJ_EXPECT(json.encode(root) == nospaces); } KJ_TEST("encode union") { MallocMessageBuilder message; auto root = message.getRoot(); root.setBefore("a"); root.setMiddle(44); root.setAfter("c"); JsonCodec json; root.setFoo(123); KJ_EXPECT(json.encode(root) == "{\"before\":\"a\",\"foo\":123,\"middle\":44,\"after\":\"c\"}"); root.setBar(321); KJ_EXPECT(json.encode(root) == "{\"before\":\"a\",\"middle\":44,\"bar\":321,\"after\":\"c\"}"); } KJ_TEST("decode all types") { JsonCodec json; json.setHasMode(HasMode::NON_DEFAULT); #define CASE_MAYBE_ROUNDTRIP(s, f, roundtrip) \ { \ MallocMessageBuilder message; \ auto root = message.initRoot(); \ kj::StringPtr input = s; \ json.decode(input, root); \ KJ_EXPECT((f), input, root); \ auto reencoded = json.encode(root); \ KJ_EXPECT(roundtrip == (input == reencoded), roundtrip, input, reencoded); \ } #define CASE_NO_ROUNDTRIP(s, f) CASE_MAYBE_ROUNDTRIP(s, f, false) #define CASE(s, f) CASE_MAYBE_ROUNDTRIP(s, f, true) #define CASE_THROW(s, errorMessage) \ { \ MallocMessageBuilder message; \ auto root = message.initRoot(); \ KJ_EXPECT_THROW_MESSAGE(errorMessage, json.decode(s, root)); \ } #define CASE_THROW_RECOVERABLE(s, errorMessage) \ { \ MallocMessageBuilder message; \ auto root = message.initRoot(); \ KJ_EXPECT_THROW_RECOVERABLE_MESSAGE(errorMessage, json.decode(s, root)); \ } CASE(R"({})", root.getBoolField() == false); CASE_NO_ROUNDTRIP(R"({"unknownField":7})", root.getBoolField() == false); CASE(R"({"boolField":true})", root.getBoolField() == true); CASE(R"({"int8Field":-128})", root.getInt8Field() == -128); CASE_NO_ROUNDTRIP(R"({"int8Field":"127"})", root.getInt8Field() == 127); CASE_THROW_RECOVERABLE(R"({"int8Field":"-129"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"int8Field":128})", "Value out-of-range"); CASE(R"({"int16Field":-32768})", root.getInt16Field() == -32768); CASE_NO_ROUNDTRIP(R"({"int16Field":"32767"})", root.getInt16Field() == 32767); CASE_THROW_RECOVERABLE(R"({"int16Field":"-32769"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"int16Field":32768})", "Value out-of-range"); CASE(R"({"int32Field":-2147483648})", root.getInt32Field() == -2147483648); CASE_NO_ROUNDTRIP(R"({"int32Field":"2147483647"})", root.getInt32Field() == 2147483647); CASE_NO_ROUNDTRIP(R"({"int64Field":-9007199254740992})", root.getInt64Field() == -9007199254740992LL); CASE_NO_ROUNDTRIP(R"({"int64Field":9007199254740991})", root.getInt64Field() == 9007199254740991LL); CASE(R"({"int64Field":"-9223372036854775808"})", root.getInt64Field() == -9223372036854775808ULL); CASE(R"({"int64Field":"9223372036854775807"})", root.getInt64Field() == 9223372036854775807LL); CASE_THROW_RECOVERABLE(R"({"int64Field":"-9223372036854775809"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"int64Field":"9223372036854775808"})", "Value out-of-range"); CASE(R"({"uInt8Field":255})", root.getUInt8Field() == 255); CASE_NO_ROUNDTRIP(R"({"uInt8Field":"0"})", root.getUInt8Field() == 0); CASE_THROW_RECOVERABLE(R"({"uInt8Field":"256"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"uInt8Field":-1})", "Value out-of-range"); CASE(R"({"uInt16Field":65535})", root.getUInt16Field() == 65535); CASE_NO_ROUNDTRIP(R"({"uInt16Field":"0"})", root.getUInt16Field() == 0); CASE_THROW_RECOVERABLE(R"({"uInt16Field":"655356"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"uInt16Field":-1})", "Value out-of-range"); CASE(R"({"uInt32Field":4294967295})", root.getUInt32Field() == 4294967295); CASE_NO_ROUNDTRIP(R"({"uInt32Field":"0"})", root.getUInt32Field() == 0); CASE_THROW_RECOVERABLE(R"({"uInt32Field":"42949672956"})", "Value out-of-range"); CASE_THROW_RECOVERABLE(R"({"uInt32Field":-1})", "Value out-of-range"); CASE_NO_ROUNDTRIP(R"({"uInt64Field":9007199254740991})", root.getUInt64Field() == 9007199254740991ULL); CASE(R"({"uInt64Field":"18446744073709551615"})", root.getUInt64Field() == 18446744073709551615ULL); CASE_NO_ROUNDTRIP(R"({"uInt64Field":"0"})", root.getUInt64Field() == 0); CASE_THROW_RECOVERABLE(R"({"uInt64Field":"18446744073709551616"})", "Value out-of-range"); CASE_NO_ROUNDTRIP(R"({"float32Field":0})", root.getFloat32Field() == 0); CASE(R"({"float32Field":4.5})", root.getFloat32Field() == 4.5); CASE_NO_ROUNDTRIP(R"({"float32Field":null})", kj::isNaN(root.getFloat32Field())); CASE(R"({"float32Field":"NaN"})", kj::isNaN(root.getFloat32Field())); CASE_NO_ROUNDTRIP(R"({"float32Field":"nan"})", kj::isNaN(root.getFloat32Field())); CASE(R"({"float32Field":"Infinity"})", root.getFloat32Field() == kj::inf()); CASE(R"({"float32Field":"-Infinity"})", root.getFloat32Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":"infinity"})", root.getFloat32Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":"-infinity"})", root.getFloat32Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":"INF"})", root.getFloat32Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":"-INF"})", root.getFloat32Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":1e39})", root.getFloat32Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float32Field":-1e39})", root.getFloat32Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":0})", root.getFloat64Field() == 0); CASE(R"({"float64Field":4.5})", root.getFloat64Field() == 4.5); CASE_NO_ROUNDTRIP(R"({"float64Field":null})", kj::isNaN(root.getFloat64Field())); CASE(R"({"float64Field":"NaN"})", kj::isNaN(root.getFloat64Field())); CASE_NO_ROUNDTRIP(R"({"float64Field":"nan"})", kj::isNaN(root.getFloat64Field())); CASE(R"({"float64Field":"Infinity"})", root.getFloat64Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":"infinity"})", root.getFloat64Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":"-infinity"})", root.getFloat64Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":"INF"})", root.getFloat64Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":"-INF"})", root.getFloat64Field() == -kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":1e309})", root.getFloat64Field() == kj::inf()); CASE_NO_ROUNDTRIP(R"({"float64Field":-1e309})", root.getFloat64Field() == -kj::inf()); CASE(R"({"textField":"hello"})", kj::str("hello") == root.getTextField()); CASE(R"({"dataField":[7,0,122]})", kj::heapArray({7,0,122}).asPtr() == root.getDataField()); CASE(R"({"structField":{}})", root.hasStructField() == true); CASE(R"({"structField":{}})", root.getStructField().getBoolField() == false); CASE_NO_ROUNDTRIP(R"({"structField":{"boolField":false}})", root.getStructField().getBoolField() == false); CASE(R"({"structField":{"boolField":true}})", root.getStructField().getBoolField() == true); CASE(R"({"enumField":"bar"})", root.getEnumField() == TestEnum::BAR); CASE_NO_ROUNDTRIP(R"({"textField":"foo\u1234bar"})", kj::str(u8"foo\u1234bar") == root.getTextField()); CASE_THROW_RECOVERABLE(R"({"structField":null})", "Expected object value"); CASE_THROW_RECOVERABLE(R"({"structList":null})", "Expected list value"); CASE_THROW_RECOVERABLE(R"({"boolList":null})", "Expected list value"); CASE_THROW_RECOVERABLE(R"({"structList":[null]})", "Expected object value"); CASE_THROW_RECOVERABLE(R"({"int64Field":"177a"})", "String does not contain valid"); CASE_THROW_RECOVERABLE(R"({"uInt64Field":"177a"})", "String does not contain valid"); CASE_THROW_RECOVERABLE(R"({"float64Field":"177a"})", "String does not contain valid"); CASE(R"({})", root.hasBoolList() == false); CASE(R"({"boolList":[]})", root.hasBoolList() == true); CASE(R"({"boolList":[]})", root.getBoolList().size() == 0); CASE(R"({"boolList":[false]})", root.getBoolList().size() == 1); CASE(R"({"boolList":[false]})", root.getBoolList()[0] == false); CASE(R"({"boolList":[true]})", root.getBoolList()[0] == true); CASE(R"({"int8List":[7]})", root.getInt8List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"int8List":["7"]})", root.getInt8List()[0] == 7); CASE(R"({"int16List":[7]})", root.getInt16List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"int16List":["7"]})", root.getInt16List()[0] == 7); CASE(R"({"int32List":[7]})", root.getInt32List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"int32List":["7"]})", root.getInt32List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"int64List":[7]})", root.getInt64List()[0] == 7); CASE(R"({"int64List":["7"]})", root.getInt64List()[0] == 7); CASE(R"({"uInt8List":[7]})", root.getUInt8List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"uInt8List":["7"]})", root.getUInt8List()[0] == 7); CASE(R"({"uInt16List":[7]})", root.getUInt16List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"uInt16List":["7"]})", root.getUInt16List()[0] == 7); CASE(R"({"uInt32List":[7]})", root.getUInt32List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"uInt32List":["7"]})", root.getUInt32List()[0] == 7); CASE_NO_ROUNDTRIP(R"({"uInt64List":[7]})", root.getUInt64List()[0] == 7); CASE(R"({"uInt64List":["7"]})", root.getUInt64List()[0] == 7); CASE(R"({"float32List":[4.5]})", root.getFloat32List()[0] == 4.5); CASE_NO_ROUNDTRIP(R"({"float32List":["4.5"]})", root.getFloat32List()[0] == 4.5); CASE_NO_ROUNDTRIP(R"({"float32List":[null]})", kj::isNaN(root.getFloat32List()[0])); CASE(R"({"float32List":["NaN"]})", kj::isNaN(root.getFloat32List()[0])); CASE(R"({"float32List":["Infinity"]})", root.getFloat32List()[0] == kj::inf()); CASE(R"({"float32List":["-Infinity"]})", root.getFloat32List()[0] == -kj::inf()); CASE(R"({"float64List":[4.5]})", root.getFloat64List()[0] == 4.5); CASE_NO_ROUNDTRIP(R"({"float64List":["4.5"]})", root.getFloat64List()[0] == 4.5); CASE_NO_ROUNDTRIP(R"({"float64List":[null]})", kj::isNaN(root.getFloat64List()[0])); CASE(R"({"float64List":["NaN"]})", kj::isNaN(root.getFloat64List()[0])); CASE(R"({"float64List":["Infinity"]})", root.getFloat64List()[0] == kj::inf()); CASE(R"({"float64List":["-Infinity"]})", root.getFloat64List()[0] == -kj::inf()); CASE(R"({"textList":["hello"]})", kj::str("hello") == root.getTextList()[0]); CASE(R"({"dataList":[[7,0,122]]})", kj::heapArray({7,0,122}).asPtr() == root.getDataList()[0]); CASE(R"({"structList":[{}]})", root.hasStructList() == true); CASE(R"({"structList":[{}]})", root.getStructList()[0].getBoolField() == false); CASE_NO_ROUNDTRIP(R"({"structList":[{"boolField":false}]})", root.getStructList()[0].getBoolField() == false); CASE(R"({"structList":[{"boolField":true}]})", root.getStructList()[0].getBoolField() == true); CASE(R"({"enumList":["bar"]})", root.getEnumList()[0] == TestEnum::BAR); #undef CASE_MAYBE_ROUNDTRIP #undef CASE_NO_ROUNDTRIP #undef CASE #undef CASE_THROW #undef CASE_THROW_RECOVERABLE } KJ_TEST("decode test message") { MallocMessageBuilder message; auto root = message.getRoot(); initTestMessage(root); JsonCodec json; auto encoded = json.encode(root); MallocMessageBuilder decodedMessage; auto decodedRoot = decodedMessage.initRoot(); json.decode(encoded, decodedRoot); KJ_EXPECT(root.toString().flatten() == decodedRoot.toString().flatten()); } KJ_TEST("basic json decoding") { // TODO(cleanup): this test is a mess! JsonCodec json; { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("null", root); KJ_EXPECT(root.which() == JsonValue::NULL_); KJ_EXPECT(root.getNull() == VOID); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("false", root); KJ_EXPECT(root.which() == JsonValue::BOOLEAN); KJ_EXPECT(root.getBoolean() == false); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("true", root); KJ_EXPECT(root.which() == JsonValue::BOOLEAN); KJ_EXPECT(root.getBoolean() == true); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("\"foo\"", root); KJ_EXPECT(root.which() == JsonValue::STRING); KJ_EXPECT(kj::str("foo") == root.getString()); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"("\"")", root); KJ_EXPECT(root.which() == JsonValue::STRING); KJ_EXPECT(kj::str("\"") == root.getString()); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"("\\abc\"d\\e")", root); KJ_EXPECT(root.which() == JsonValue::STRING); KJ_EXPECT(kj::str("\\abc\"d\\e") == root.getString()); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"("\"\\\/\b\f\n\r\t\u0003abc\u0064\u0065f")", root); KJ_EXPECT(root.which() == JsonValue::STRING); KJ_EXPECT(kj::str("\"\\/\b\f\n\r\t\x03""abcdef") == root.getString(), root.getString()); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("[]", root); KJ_EXPECT(root.which() == JsonValue::ARRAY, (uint)root.which()); KJ_EXPECT(root.getArray().size() == 0); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("[true]", root); KJ_EXPECT(root.which() == JsonValue::ARRAY); auto array = root.getArray(); KJ_EXPECT(array.size() == 1, array.size()); KJ_EXPECT(root.getArray()[0].which() == JsonValue::BOOLEAN); KJ_EXPECT(root.getArray()[0].getBoolean() == true); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(" [ true , false\t\n , null]", root); KJ_EXPECT(root.which() == JsonValue::ARRAY); auto array = root.getArray(); KJ_EXPECT(array.size() == 3); KJ_EXPECT(array[0].which() == JsonValue::BOOLEAN); KJ_EXPECT(array[0].getBoolean() == true); KJ_EXPECT(array[1].which() == JsonValue::BOOLEAN); KJ_EXPECT(array[1].getBoolean() == false); KJ_EXPECT(array[2].which() == JsonValue::NULL_); KJ_EXPECT(array[2].getNull() == VOID); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("{}", root); KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which()); KJ_EXPECT(root.getObject().size() == 0); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("\r\n\t {\r\n\t }\r\n\t ", root); KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which()); KJ_EXPECT(root.getObject().size() == 0); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"({"some": null})", root); KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which()); auto object = root.getObject(); KJ_EXPECT(object.size() == 1); KJ_EXPECT(kj::str("some") == object[0].getName()); KJ_EXPECT(object[0].getValue().which() == JsonValue::NULL_); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"({"foo\n\tbaz": "a val", "bar": ["a", -5.5e11, { "z": {}}]})", root); KJ_EXPECT(root.which() == JsonValue::OBJECT, (uint)root.which()); auto object = root.getObject(); KJ_EXPECT(object.size() == 2); KJ_EXPECT(kj::str("foo\n\tbaz") == object[0].getName()); KJ_EXPECT(object[0].getValue().which() == JsonValue::STRING); KJ_EXPECT(kj::str("a val") == object[0].getValue().getString()); KJ_EXPECT(kj::str("bar") == object[1].getName()); KJ_EXPECT(object[1].getValue().which() == JsonValue::ARRAY); auto array = object[1].getValue().getArray(); KJ_EXPECT(array.size() == 3, array.size()); KJ_EXPECT(array[0].which() == JsonValue::STRING); KJ_EXPECT(kj::str("a") == array[0].getString()); KJ_EXPECT(array[1].which() == JsonValue::NUMBER); KJ_EXPECT(array[1].getNumber() == -5.5e11); KJ_EXPECT(array[2].which() == JsonValue::OBJECT); KJ_EXPECT(array[2].getObject().size() == 1); KJ_EXPECT(array[2].getObject()[0].getValue().which() == JsonValue::OBJECT); KJ_EXPECT(array[2].getObject()[0].getValue().getObject().size() == 0); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("123", root); KJ_EXPECT(root.which() == JsonValue::NUMBER); KJ_EXPECT(root.getNumber() == 123); } { MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("input", json.decodeRaw("z", root)); } { MallocMessageBuilder message; auto root = message.initRoot(); // Leading + not allowed in numbers. KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("+123", root)); } { MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("[00]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected", json.decodeRaw("[01]", root)); } { MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root)); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("-5", root); KJ_EXPECT(root.which() == JsonValue::NUMBER); KJ_EXPECT(root.getNumber() == -5); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw("-5.5", root); KJ_EXPECT(root.which() == JsonValue::NUMBER); KJ_EXPECT(root.getNumber() == -5.5); } { MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("a", root)); KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("[", root)); KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("{", root)); KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("\"\\u\"", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[}]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1, , ]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[,]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[true,]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[, 1]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1\"\"]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("[1,, \"\"]", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\"a\"1: 0}", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw(R"({"some": null,})", root)); KJ_EXPECT_THROW_MESSAGE("Input remains", json.decodeRaw("11a", root)); KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root)); KJ_EXPECT_THROW_MESSAGE("Invalid escape", json.decodeRaw(R"("\z")", root)); { // TODO(msvc): This raw string literal currently confuses MSVC's preprocessor, so I hoisted // it outside the macro. auto f = [&] { json.decodeRaw(R"(["\n\", 3])", root); }; KJ_EXPECT_THROW_MESSAGE("ends prematurely", f()); } KJ_EXPECT_THROW_MESSAGE("Invalid hex", json.decodeRaw(R"("\u12zz")", root)); KJ_EXPECT_THROW_MESSAGE("ends prematurely", json.decodeRaw("-", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("--", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("\f{}", root)); KJ_EXPECT_THROW_MESSAGE("Unexpected input", json.decodeRaw("{\v}", root)); } { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(R"("\u007f")", root); KJ_EXPECT(root.which() == JsonValue::STRING); char utf_buffer[] = {127, 0}; KJ_EXPECT(kj::str(utf_buffer) == root.getString()); } } KJ_TEST("maximum nesting depth") { JsonCodec json; auto input = kj::str(R"({"foo": "a", "bar": ["b", { "baz": [-5.5e11] }, [ [ 1 ], { "z": 2 }]]})"); // `input` has a maximum nesting depth of 4, reached 3 times. { MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(input, root); } { json.setMaxNestingDepth(0); MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("nest", json.decodeRaw(input, root)); } { json.setMaxNestingDepth(3); MallocMessageBuilder message; auto root = message.initRoot(); KJ_EXPECT_THROW_MESSAGE("nest", json.decodeRaw(input, root)); } { json.setMaxNestingDepth(4); MallocMessageBuilder message; auto root = message.initRoot(); json.decodeRaw(input, root); } } KJ_TEST("unknown fields") { JsonCodec json; MallocMessageBuilder message; auto root = message.initRoot(); auto valid = R"({"foo": "a"})"_kj; auto unknown = R"({"foo": "a", "unknown-field": "b"})"_kj; json.decode(valid, root); json.decode(unknown, root); json.setRejectUnknownFields(true); json.decode(valid, root); KJ_EXPECT_THROW_MESSAGE("Unknown field", json.decode(unknown, root)); // Verify unknown field rejection still works when handling by annotation. json.handleByAnnotation(); KJ_EXPECT_THROW_MESSAGE("Unknown field", json.decode(unknown, root)); } class TestCallHandler: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, Text::Reader input, JsonValue::Builder output) const override { auto call = output.initCall(); call.setFunction("Frob"); auto params = call.initParams(2); params[0].setNumber(123); params[1].setString(input); } Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const override { KJ_UNIMPLEMENTED("TestHandler::decode"); } }; class TestDynamicStructHandler: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, DynamicStruct::Reader input, JsonValue::Builder output) const override { auto fields = input.getSchema().getFields(); auto items = output.initArray(fields.size()); for (auto field: fields) { KJ_REQUIRE(field.getIndex() < items.size()); auto item = items[field.getIndex()]; if (input.has(field)) { codec.encode(input.get(field), field.getType(), item); } else { item.setNull(); } } } void decode(const JsonCodec& codec, JsonValue::Reader input, DynamicStruct::Builder output) const override { auto orphanage = Orphanage::getForMessageContaining(output); auto fields = output.getSchema().getFields(); auto items = input.getArray(); for (auto field: fields) { KJ_REQUIRE(field.getIndex() < items.size()); auto item = items[field.getIndex()]; if (!item.isNull()) { output.adopt(field, codec.decode(item, field.getType(), orphanage)); } } } }; class TestStructHandler: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, test::TestOldVersion::Reader input, JsonValue::Builder output) const override { dynamicHandler.encode(codec, input, output); } void decode(const JsonCodec& codec, JsonValue::Reader input, test::TestOldVersion::Builder output) const override { dynamicHandler.decode(codec, input, output); } private: TestDynamicStructHandler dynamicHandler; }; KJ_TEST("register custom encoding handlers") { JsonCodec json; TestStructHandler structHandler; json.addTypeHandler(structHandler); // JSON decoder can't parse calls back, so test only encoder here TestCallHandler callHandler; json.addTypeHandler(callHandler); MallocMessageBuilder message; auto root = message.getRoot(); root.setOld1(123); root.setOld2("foo"); KJ_EXPECT(json.encode(root) == "[\"123\",Frob(123,\"foo\"),null]"); } KJ_TEST("register custom roundtrip handler") { for (auto i = 1; i <= 2; i++) { JsonCodec json; TestStructHandler staticHandler; TestDynamicStructHandler dynamicHandler; kj::String encoded; if (i == 1) { // first iteration: test with explicit struct handler json.addTypeHandler(staticHandler); } else { // second iteration: same checks, but with DynamicStruct handler json.addTypeHandler(StructSchema::from(), dynamicHandler); } { MallocMessageBuilder message; auto root = message.getRoot(); root.setOld1(123); root.initOld3().setOld2("foo"); encoded = json.encode(root); KJ_EXPECT(encoded == "[\"123\",null,[\"0\",\"foo\",null]]"); } { MallocMessageBuilder message; auto root = message.getRoot(); json.decode(encoded, root); KJ_EXPECT(root.getOld1() == 123); KJ_EXPECT(!root.hasOld2()); auto nested = root.getOld3(); KJ_EXPECT(nested.getOld1() == 0); KJ_EXPECT("foo" == nested.getOld2()); KJ_EXPECT(!nested.hasOld3()); } } } KJ_TEST("register field handler") { TestStructHandler handler; JsonCodec json; json.addFieldHandler(StructSchema::from().getFieldByName("old3"), handler); kj::String encoded; { MallocMessageBuilder message; auto root = message.getRoot(); root.setOld1(123); root.setOld2("foo"); auto nested = root.initOld3(); nested.setOld2("bar"); encoded = json.encode(root); KJ_EXPECT(encoded == "{\"old1\":\"123\",\"old2\":\"foo\",\"old3\":[\"0\",\"bar\",null]}") } { MallocMessageBuilder message; auto root = message.getRoot(); json.decode(encoded, root); KJ_EXPECT(root.getOld1() == 123); KJ_EXPECT("foo" == root.getOld2()); auto nested = root.getOld3(); KJ_EXPECT(nested.getOld1() == 0); KJ_EXPECT("bar" == nested.getOld2()); KJ_EXPECT(!nested.hasOld3()); } } class TestCapabilityHandler: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, test::TestInterface::Client input, JsonValue::Builder output) const override { KJ_UNIMPLEMENTED("TestCapabilityHandler::encode"); } test::TestInterface::Client decode( const JsonCodec& codec, JsonValue::Reader input) const override { return nullptr; } }; KJ_TEST("register capability handler") { // This test currently only checks that this compiles, which at one point wasn't the caes. // TODO(test): Actually run some code here. TestCapabilityHandler handler; JsonCodec json; json.addTypeHandler(handler); } static constexpr kj::StringPtr GOLDEN_ANNOTATED = R"({ "names-can_contain!anything Really": "foo", "flatFoo": 123, "flatBar": "abc", "renamed-flatBaz": {"hello": true}, "flatQux": "cba", "pfx.foo": "this is a long string in order to force multi-line pretty printing", "pfx.renamed-bar": 321, "pfx.baz": {"hello": true}, "pfx.xfp.qux": "fed", "union-type": "renamed-bar", "barMember": 789, "multiMember": "ghi", "dependency": {"renamed-foo": "corge"}, "simpleGroup": {"renamed-grault": "garply"}, "enums": ["qux", "renamed-bar", "foo", "renamed-baz"], "innerJson": [123, "hello", {"object": true}], "customFieldHandler": "add-prefix-waldo", "testBase64": "ZnJlZA==", "testHex": "706c756768", "bUnion": "renamed-bar", "bValue": 678, "externalUnion": {"type": "bar", "value": "cba"}, "unionWithVoid": {"type": "voidValue"} })"_kj; static constexpr kj::StringPtr GOLDEN_ANNOTATED_REVERSE = R"({ "unionWithVoid": {"type": "voidValue"}, "externalUnion": {"type": "bar", "value": "cba"}, "bValue": 678, "bUnion": "renamed-bar", "testHex": "706c756768", "testBase64": "ZnJlZA==", "customFieldHandler": "add-prefix-waldo", "innerJson": [123, "hello", {"object": true}], "enums": ["qux", "renamed-bar", "foo", "renamed-baz"], "simpleGroup": { "renamed-grault": "garply" }, "dependency": { "renamed-foo": "corge" }, "multiMember": "ghi", "barMember": 789, "union-type": "renamed-bar", "pfx.xfp.qux": "fed", "pfx.baz": {"hello": true}, "pfx.renamed-bar": 321, "pfx.foo": "this is a long string in order to force multi-line pretty printing", "flatQux": "cba", "renamed-flatBaz": {"hello": true}, "flatBar": "abc", "flatFoo": 123, "names-can_contain!anything Really": "foo" })"_kj; class PrefixAdder: public JsonCodec::Handler { public: void encode(const JsonCodec& codec, capnp::Text::Reader input, JsonValue::Builder output) const { output.setString(kj::str("add-prefix-", input)); } Orphan decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const { return orphanage.newOrphanCopy(capnp::Text::Reader(input.getString().slice(11))); } }; KJ_TEST("rename fields") { JsonCodec json; json.handleByAnnotation(); json.setPrettyPrint(true); PrefixAdder customHandler; json.addFieldHandler(Schema::from().getFieldByName("customFieldHandler"), customHandler); kj::String goldenText; { MallocMessageBuilder message; auto root = message.getRoot(); root.setSomeField("foo"); auto aGroup = root.getAGroup(); aGroup.setFlatFoo(123); aGroup.setFlatBar("abc"); aGroup.getFlatBaz().setHello(true); aGroup.getDoubleFlat().setFlatQux("cba"); auto prefixedGroup = root.getPrefixedGroup(); prefixedGroup.setFoo("this is a long string in order to force multi-line pretty printing"); prefixedGroup.setBar(321); prefixedGroup.getBaz().setHello(true); prefixedGroup.getMorePrefix().setQux("fed"); auto unionBar = root.getAUnion().initBar(); unionBar.setBarMember(789); unionBar.setMultiMember("ghi"); root.initDependency().setFoo("corge"); root.initSimpleGroup().setGrault("garply"); root.setEnums({ TestJsonAnnotatedEnum::QUX, TestJsonAnnotatedEnum::BAR, TestJsonAnnotatedEnum::FOO, TestJsonAnnotatedEnum::BAZ }); auto val = root.initInnerJson(); auto arr = val.initArray(3); arr[0].setNumber(123); arr[1].setString("hello"); auto field = arr[2].initObject(1)[0]; field.setName("object"); field.initValue().setBoolean(true); root.setCustomFieldHandler("waldo"); root.setTestBase64("fred"_kj.asBytes()); root.setTestHex("plugh"_kj.asBytes()); root.getBUnion().setBar(678); root.initExternalUnion().initBar().setValue("cba"); root.initUnionWithVoid().setVoidValue(); auto encoded = json.encode(root.asReader()); KJ_EXPECT(encoded == GOLDEN_ANNOTATED, encoded); goldenText = kj::str(root); } { MallocMessageBuilder message; auto root = message.getRoot(); json.decode(GOLDEN_ANNOTATED, root); KJ_EXPECT(kj::str(root) == goldenText, root, goldenText); } { // Try parsing in reverse, mostly to test that union tags can come after content. MallocMessageBuilder message; auto root = message.getRoot(); json.decode(GOLDEN_ANNOTATED_REVERSE, root); KJ_EXPECT(kj::str(root) == goldenText, root, goldenText); } } KJ_TEST("base64 union encoded correctly") { // At one point field handlers were not correctly applied when the field was a member of a union // in a type that was handled by annotation. JsonCodec json; json.handleByAnnotation(); json.setPrettyPrint(true); MallocMessageBuilder message; auto root = message.getRoot(); root.initFoo(5); KJ_EXPECT(json.encode(root) == "{\"foo\": \"AAAAAAA=\"}", json.encode(root)); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc-twoparty.capnp.c++0000644000175000017500000004361714712011043022703 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: rpc-twoparty.capnp #include "rpc-twoparty.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<26> b_9fd69ebc87b9719c = { { 0, 0, 0, 0, 5, 0, 6, 0, 156, 113, 185, 135, 188, 158, 214, 159, 25, 0, 0, 0, 2, 0, 0, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 242, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 83, 105, 100, 101, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 101, 114, 118, 101, 114, 0, 0, 99, 108, 105, 101, 110, 116, 0, 0, } }; ::capnp::word const* const bp_9fd69ebc87b9719c = b_9fd69ebc87b9719c.words; #if !CAPNP_LITE static const uint16_t m_9fd69ebc87b9719c[] = {1, 0}; const ::capnp::_::RawSchema s_9fd69ebc87b9719c = { 0x9fd69ebc87b9719c, b_9fd69ebc87b9719c.words, 26, nullptr, m_9fd69ebc87b9719c, 0, 2, nullptr, nullptr, nullptr, { &s_9fd69ebc87b9719c, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE CAPNP_DEFINE_ENUM(Side_9fd69ebc87b9719c, 9fd69ebc87b9719c); static const ::capnp::_::AlignedData<33> b_d20b909fee733a8e = { { 0, 0, 0, 0, 5, 0, 6, 0, 142, 58, 115, 238, 159, 144, 11, 210, 25, 0, 0, 0, 1, 0, 1, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 86, 97, 116, 73, 100, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 115, 105, 100, 101, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 156, 113, 185, 135, 188, 158, 214, 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d20b909fee733a8e = b_d20b909fee733a8e.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d20b909fee733a8e[] = { &s_9fd69ebc87b9719c, }; static const uint16_t m_d20b909fee733a8e[] = {0}; static const uint16_t i_d20b909fee733a8e[] = {0}; const ::capnp::_::RawSchema s_d20b909fee733a8e = { 0xd20b909fee733a8e, b_d20b909fee733a8e.words, 33, d_d20b909fee733a8e, m_d20b909fee733a8e, 1, 1, i_d20b909fee733a8e, nullptr, nullptr, { &s_d20b909fee733a8e, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<34> b_b88d09a9c5f39817 = { { 0, 0, 0, 0, 5, 0, 6, 0, 23, 152, 243, 197, 169, 9, 141, 184, 25, 0, 0, 0, 1, 0, 1, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 80, 114, 111, 118, 105, 115, 105, 111, 110, 73, 100, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 106, 111, 105, 110, 73, 100, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b88d09a9c5f39817 = b_b88d09a9c5f39817.words; #if !CAPNP_LITE static const uint16_t m_b88d09a9c5f39817[] = {0}; static const uint16_t i_b88d09a9c5f39817[] = {0}; const ::capnp::_::RawSchema s_b88d09a9c5f39817 = { 0xb88d09a9c5f39817, b_b88d09a9c5f39817.words, 34, nullptr, m_b88d09a9c5f39817, 0, 1, i_b88d09a9c5f39817, nullptr, nullptr, { &s_b88d09a9c5f39817, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<18> b_89f389b6fd4082c1 = { { 0, 0, 0, 0, 5, 0, 6, 0, 193, 130, 64, 253, 182, 137, 243, 137, 25, 0, 0, 0, 1, 0, 0, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 82, 101, 99, 105, 112, 105, 101, 110, 116, 73, 100, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, } }; ::capnp::word const* const bp_89f389b6fd4082c1 = b_89f389b6fd4082c1.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_89f389b6fd4082c1 = { 0x89f389b6fd4082c1, b_89f389b6fd4082c1.words, 18, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_89f389b6fd4082c1, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<19> b_b47f4979672cb59d = { { 0, 0, 0, 0, 5, 0, 6, 0, 157, 181, 44, 103, 121, 73, 127, 180, 25, 0, 0, 0, 1, 0, 0, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 74, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 84, 104, 105, 114, 100, 80, 97, 114, 116, 121, 67, 97, 112, 73, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, } }; ::capnp::word const* const bp_b47f4979672cb59d = b_b47f4979672cb59d.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_b47f4979672cb59d = { 0xb47f4979672cb59d, b_b47f4979672cb59d.words, 19, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_b47f4979672cb59d, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<65> b_95b29059097fca83 = { { 0, 0, 0, 0, 5, 0, 6, 0, 131, 202, 127, 9, 89, 144, 178, 149, 25, 0, 0, 0, 1, 0, 1, 0, 161, 242, 218, 92, 136, 199, 132, 161, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 42, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 74, 111, 105, 110, 75, 101, 121, 80, 97, 114, 116, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 106, 111, 105, 110, 73, 100, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 116, 67, 111, 117, 110, 116, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 116, 78, 117, 109, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_95b29059097fca83 = b_95b29059097fca83.words; #if !CAPNP_LITE static const uint16_t m_95b29059097fca83[] = {0, 1, 2}; static const uint16_t i_95b29059097fca83[] = {0, 1, 2}; const ::capnp::_::RawSchema s_95b29059097fca83 = { 0x95b29059097fca83, b_95b29059097fca83.words, 65, nullptr, m_95b29059097fca83, 0, 3, i_95b29059097fca83, nullptr, nullptr, { &s_95b29059097fca83, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<65> b_9d263a3630b7ebee = { { 0, 0, 0, 0, 5, 0, 6, 0, 238, 235, 183, 48, 54, 58, 38, 157, 25, 0, 0, 0, 1, 0, 1, 0, 161, 242, 218, 92, 136, 199, 132, 161, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 34, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 114, 112, 99, 45, 116, 119, 111, 112, 97, 114, 116, 121, 46, 99, 97, 112, 110, 112, 58, 74, 111, 105, 110, 82, 101, 115, 117, 108, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 32, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 106, 111, 105, 110, 73, 100, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 117, 99, 99, 101, 101, 100, 101, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9d263a3630b7ebee = b_9d263a3630b7ebee.words; #if !CAPNP_LITE static const uint16_t m_9d263a3630b7ebee[] = {2, 0, 1}; static const uint16_t i_9d263a3630b7ebee[] = {0, 1, 2}; const ::capnp::_::RawSchema s_9d263a3630b7ebee = { 0x9d263a3630b7ebee, b_9d263a3630b7ebee.words, 65, nullptr, m_9d263a3630b7ebee, 0, 3, i_9d263a3630b7ebee, nullptr, nullptr, { &s_9d263a3630b7ebee, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace rpc { namespace twoparty { // VatId #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t VatId::_capnpPrivate::dataWordSize; constexpr uint16_t VatId::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind VatId::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* VatId::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // ProvisionId #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t ProvisionId::_capnpPrivate::dataWordSize; constexpr uint16_t ProvisionId::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind ProvisionId::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* ProvisionId::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // RecipientId #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t RecipientId::_capnpPrivate::dataWordSize; constexpr uint16_t RecipientId::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind RecipientId::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* RecipientId::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // ThirdPartyCapId #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t ThirdPartyCapId::_capnpPrivate::dataWordSize; constexpr uint16_t ThirdPartyCapId::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind ThirdPartyCapId::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* ThirdPartyCapId::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // JoinKeyPart #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t JoinKeyPart::_capnpPrivate::dataWordSize; constexpr uint16_t JoinKeyPart::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind JoinKeyPart::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* JoinKeyPart::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // JoinResult #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t JoinResult::_capnpPrivate::dataWordSize; constexpr uint16_t JoinResult::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind JoinResult::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* JoinResult::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/persistent.capnp.h0000644000175000017500000006222114731562162022315 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: persistent.capnp #pragma once #include #include #if !CAPNP_LITE #include #endif // !CAPNP_LITE #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(c8cb212fcd9f5691); CAPNP_DECLARE_SCHEMA(f76fba59183073a5); CAPNP_DECLARE_SCHEMA(b76848c18c40efbf); CAPNP_DECLARE_SCHEMA(f622595091cafb67); } // namespace schemas } // namespace capnp namespace capnp { template struct Persistent { Persistent() = delete; #if !CAPNP_LITE class Client; class Server; #endif // !CAPNP_LITE struct SaveParams; struct SaveResults; #if !CAPNP_LITE struct _capnpPrivate { CAPNP_DECLARE_INTERFACE_HEADER(c8cb212fcd9f5691) static const ::capnp::_::RawBrandedSchema::Scope brandScopes[]; static const ::capnp::_::RawBrandedSchema::Binding brandBindings[]; static const ::capnp::_::RawBrandedSchema::Dependency brandDependencies[]; static const ::capnp::_::RawBrandedSchema specificBrand; static constexpr ::capnp::_::RawBrandedSchema const* brand() { return ::capnp::_::ChooseBrand<_capnpPrivate, SturdyRef, Owner>::brand(); } }; #endif // !CAPNP_LITE }; template struct Persistent::SaveParams { SaveParams() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f76fba59183073a5, 0, 1) #if !CAPNP_LITE static const ::capnp::_::RawBrandedSchema::Scope brandScopes[]; static const ::capnp::_::RawBrandedSchema::Binding brandBindings[]; static const ::capnp::_::RawBrandedSchema specificBrand; static constexpr ::capnp::_::RawBrandedSchema const* brand() { return ::capnp::_::ChooseBrand<_capnpPrivate, SturdyRef, Owner>::brand(); } #endif // !CAPNP_LITE }; }; template struct Persistent::SaveResults { SaveResults() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(b76848c18c40efbf, 0, 1) #if !CAPNP_LITE static const ::capnp::_::RawBrandedSchema::Scope brandScopes[]; static const ::capnp::_::RawBrandedSchema::Binding brandBindings[]; static const ::capnp::_::RawBrandedSchema specificBrand; static constexpr ::capnp::_::RawBrandedSchema const* brand() { return ::capnp::_::ChooseBrand<_capnpPrivate, SturdyRef, Owner>::brand(); } #endif // !CAPNP_LITE }; }; // ======================================================================================= #if !CAPNP_LITE template class Persistent::Client : public virtual ::capnp::Capability::Client { public: typedef Persistent Calls; typedef Persistent Reads; Client(decltype(nullptr)); explicit Client(::kj::Own< ::capnp::ClientHook>&& hook); template ()>> Client(::kj::Own<_t>&& server); template ()>> Client(::kj::Promise<_t>&& promise); Client(::kj::Exception&& exception); Client(Client&) = default; Client(Client&&) = default; Client& operator=(Client& other); Client& operator=(Client&& other); template typename Persistent::Client asGeneric() { return castAs>(); } CAPNP_AUTO_IF_MSVC(::capnp::Request::SaveParams, typename ::capnp::Persistent::SaveResults>) saveRequest( ::kj::Maybe< ::capnp::MessageSize> sizeHint = nullptr); protected: Client() = default; }; template class Persistent::Server : public virtual ::capnp::Capability::Server { public: typedef Persistent Serves; ::capnp::Capability::Server::DispatchCallResult dispatchCall( uint64_t interfaceId, uint16_t methodId, ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context) override; protected: typedef ::capnp::CallContext::SaveParams, typename ::capnp::Persistent::SaveResults> SaveContext; virtual ::kj::Promise save(SaveContext context); inline typename ::capnp::Persistent::Client thisCap() { return ::capnp::Capability::Server::thisCap() .template castAs< ::capnp::Persistent>(); } ::capnp::Capability::Server::DispatchCallResult dispatchCallInternal( uint16_t methodId, ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context); }; #endif // !CAPNP_LITE template class Persistent::SaveParams::Reader { public: typedef SaveParams Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE template typename Persistent::SaveParams::Reader asPersistentGeneric() { return typename Persistent::SaveParams::Reader(_reader); } inline bool hasSealFor() const; inline ::capnp::ReaderFor getSealFor() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; template class Persistent::SaveParams::Builder { public: typedef SaveParams Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE template typename Persistent::SaveParams::Builder asPersistentGeneric() { return typename Persistent::SaveParams::Builder(_builder); } inline bool hasSealFor(); inline ::capnp::BuilderFor getSealFor(); inline void setSealFor( ::capnp::ReaderFor value); inline ::capnp::BuilderFor initSealFor(); inline ::capnp::BuilderFor initSealFor(unsigned int size); inline void adoptSealFor(::capnp::Orphan&& value); inline ::capnp::Orphan disownSealFor(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE template class Persistent::SaveParams::Pipeline { public: typedef SaveParams Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::PipelineFor getSealFor(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE template class Persistent::SaveResults::Reader { public: typedef SaveResults Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE template typename Persistent::SaveResults::Reader asPersistentGeneric() { return typename Persistent::SaveResults::Reader(_reader); } inline bool hasSturdyRef() const; inline ::capnp::ReaderFor getSturdyRef() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; template class Persistent::SaveResults::Builder { public: typedef SaveResults Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE template typename Persistent::SaveResults::Builder asPersistentGeneric() { return typename Persistent::SaveResults::Builder(_builder); } inline bool hasSturdyRef(); inline ::capnp::BuilderFor getSturdyRef(); inline void setSturdyRef( ::capnp::ReaderFor value); inline ::capnp::BuilderFor initSturdyRef(); inline ::capnp::BuilderFor initSturdyRef(unsigned int size); inline void adoptSturdyRef(::capnp::Orphan&& value); inline ::capnp::Orphan disownSturdyRef(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE template class Persistent::SaveResults::Pipeline { public: typedef SaveResults Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::PipelineFor getSturdyRef(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= #if !CAPNP_LITE template inline Persistent::Client::Client(decltype(nullptr)) : ::capnp::Capability::Client(nullptr) {} template inline Persistent::Client::Client( ::kj::Own< ::capnp::ClientHook>&& hook) : ::capnp::Capability::Client(::kj::mv(hook)) {} template template inline Persistent::Client::Client(::kj::Own<_t>&& server) : ::capnp::Capability::Client(::kj::mv(server)) {} template template inline Persistent::Client::Client(::kj::Promise<_t>&& promise) : ::capnp::Capability::Client(::kj::mv(promise)) {} template inline Persistent::Client::Client(::kj::Exception&& exception) : ::capnp::Capability::Client(::kj::mv(exception)) {} template inline typename ::capnp::Persistent::Client& Persistent::Client::operator=(Client& other) { ::capnp::Capability::Client::operator=(other); return *this; } template inline typename ::capnp::Persistent::Client& Persistent::Client::operator=(Client&& other) { ::capnp::Capability::Client::operator=(kj::mv(other)); return *this; } #endif // !CAPNP_LITE template inline bool Persistent::SaveParams::Reader::hasSealFor() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } template inline bool Persistent::SaveParams::Builder::hasSealFor() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } template inline ::capnp::ReaderFor Persistent::SaveParams::Reader::getSealFor() const { return ::capnp::_::PointerHelpers::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } template inline ::capnp::BuilderFor Persistent::SaveParams::Builder::getSealFor() { return ::capnp::_::PointerHelpers::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE template inline ::capnp::PipelineFor Persistent::SaveParams::Pipeline::getSealFor() { return ::capnp::PipelineFor(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE template inline void Persistent::SaveParams::Builder::setSealFor( ::capnp::ReaderFor value) { ::capnp::_::PointerHelpers::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } template inline ::capnp::BuilderFor Persistent::SaveParams::Builder::initSealFor() { return ::capnp::_::PointerHelpers::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } template inline ::capnp::BuilderFor Persistent::SaveParams::Builder::initSealFor(unsigned int size) { return ::capnp::_::PointerHelpers::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } template inline void Persistent::SaveParams::Builder::adoptSealFor( ::capnp::Orphan&& value) { ::capnp::_::PointerHelpers::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } template inline ::capnp::Orphan Persistent::SaveParams::Builder::disownSealFor() { return ::capnp::_::PointerHelpers::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } // Persistent::SaveParams #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template constexpr uint16_t Persistent::SaveParams::_capnpPrivate::dataWordSize; template constexpr uint16_t Persistent::SaveParams::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template constexpr ::capnp::Kind Persistent::SaveParams::_capnpPrivate::kind; template constexpr ::capnp::_::RawSchema const* Persistent::SaveParams::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template const ::capnp::_::RawBrandedSchema::Scope Persistent::SaveParams::_capnpPrivate::brandScopes[] = { { 0xc8cb212fcd9f5691, brandBindings + 0, 2, false}, }; template const ::capnp::_::RawBrandedSchema::Binding Persistent::SaveParams::_capnpPrivate::brandBindings[] = { ::capnp::_::brandBindingFor(), ::capnp::_::brandBindingFor(), }; template const ::capnp::_::RawBrandedSchema Persistent::SaveParams::_capnpPrivate::specificBrand = { &::capnp::schemas::s_f76fba59183073a5, brandScopes, nullptr, 1, 0, nullptr }; #endif // !CAPNP_LITE template inline bool Persistent::SaveResults::Reader::hasSturdyRef() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } template inline bool Persistent::SaveResults::Builder::hasSturdyRef() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } template inline ::capnp::ReaderFor Persistent::SaveResults::Reader::getSturdyRef() const { return ::capnp::_::PointerHelpers::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } template inline ::capnp::BuilderFor Persistent::SaveResults::Builder::getSturdyRef() { return ::capnp::_::PointerHelpers::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE template inline ::capnp::PipelineFor Persistent::SaveResults::Pipeline::getSturdyRef() { return ::capnp::PipelineFor(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE template inline void Persistent::SaveResults::Builder::setSturdyRef( ::capnp::ReaderFor value) { ::capnp::_::PointerHelpers::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } template inline ::capnp::BuilderFor Persistent::SaveResults::Builder::initSturdyRef() { return ::capnp::_::PointerHelpers::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } template inline ::capnp::BuilderFor Persistent::SaveResults::Builder::initSturdyRef(unsigned int size) { return ::capnp::_::PointerHelpers::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } template inline void Persistent::SaveResults::Builder::adoptSturdyRef( ::capnp::Orphan&& value) { ::capnp::_::PointerHelpers::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } template inline ::capnp::Orphan Persistent::SaveResults::Builder::disownSturdyRef() { return ::capnp::_::PointerHelpers::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } // Persistent::SaveResults #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template constexpr uint16_t Persistent::SaveResults::_capnpPrivate::dataWordSize; template constexpr uint16_t Persistent::SaveResults::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template constexpr ::capnp::Kind Persistent::SaveResults::_capnpPrivate::kind; template constexpr ::capnp::_::RawSchema const* Persistent::SaveResults::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template const ::capnp::_::RawBrandedSchema::Scope Persistent::SaveResults::_capnpPrivate::brandScopes[] = { { 0xc8cb212fcd9f5691, brandBindings + 0, 2, false}, }; template const ::capnp::_::RawBrandedSchema::Binding Persistent::SaveResults::_capnpPrivate::brandBindings[] = { ::capnp::_::brandBindingFor(), ::capnp::_::brandBindingFor(), }; template const ::capnp::_::RawBrandedSchema Persistent::SaveResults::_capnpPrivate::specificBrand = { &::capnp::schemas::s_b76848c18c40efbf, brandScopes, nullptr, 1, 0, nullptr }; #endif // !CAPNP_LITE #if !CAPNP_LITE template CAPNP_AUTO_IF_MSVC(::capnp::Request::SaveParams, typename ::capnp::Persistent::SaveResults>) Persistent::Client::saveRequest(::kj::Maybe< ::capnp::MessageSize> sizeHint) { return newCall::SaveParams, typename ::capnp::Persistent::SaveResults>( 0xc8cb212fcd9f5691ull, 0, sizeHint, {false}); } template ::kj::Promise Persistent::Server::save(SaveContext) { return ::capnp::Capability::Server::internalUnimplemented( "capnp/persistent.capnp:Persistent", "save", 0xc8cb212fcd9f5691ull, 0); } template ::capnp::Capability::Server::DispatchCallResult Persistent::Server::dispatchCall( uint64_t interfaceId, uint16_t methodId, ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context) { switch (interfaceId) { case 0xc8cb212fcd9f5691ull: return dispatchCallInternal(methodId, context); default: return internalUnimplemented("capnp/persistent.capnp:Persistent", interfaceId); } } template ::capnp::Capability::Server::DispatchCallResult Persistent::Server::dispatchCallInternal( uint16_t methodId, ::capnp::CallContext< ::capnp::AnyPointer, ::capnp::AnyPointer> context) { switch (methodId) { case 0: return { save(::capnp::Capability::Server::internalGetTypedContext< typename ::capnp::Persistent::SaveParams, typename ::capnp::Persistent::SaveResults>(context)), false, false }; default: (void)context; return ::capnp::Capability::Server::internalUnimplemented( "capnp/persistent.capnp:Persistent", 0xc8cb212fcd9f5691ull, methodId); } } #endif // !CAPNP_LITE // Persistent #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template constexpr ::capnp::Kind Persistent::_capnpPrivate::kind; template constexpr ::capnp::_::RawSchema const* Persistent::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL template const ::capnp::_::RawBrandedSchema::Scope Persistent::_capnpPrivate::brandScopes[] = { { 0xc8cb212fcd9f5691, brandBindings + 0, 2, false}, }; template const ::capnp::_::RawBrandedSchema::Binding Persistent::_capnpPrivate::brandBindings[] = { ::capnp::_::brandBindingFor(), ::capnp::_::brandBindingFor(), }; template const ::capnp::_::RawBrandedSchema::Dependency Persistent::_capnpPrivate::brandDependencies[] = { { 33554432, ::capnp::Persistent::SaveParams::_capnpPrivate::brand() }, { 50331648, ::capnp::Persistent::SaveResults::_capnpPrivate::brand() }, }; template const ::capnp::_::RawBrandedSchema Persistent::_capnpPrivate::specificBrand = { &::capnp::schemas::s_c8cb212fcd9f5691, brandScopes, brandDependencies, 1, 2, nullptr }; #endif // !CAPNP_LITE } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/schema-parser.h0000644000175000017500000003204214712011043021527 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "schema-loader.h" #include #include CAPNP_BEGIN_HEADER namespace capnp { class ParsedSchema; class SchemaFile; class SchemaParser { // Parses `.capnp` files to produce `Schema` objects. // // This class is thread-safe, hence all its methods are const. public: SchemaParser(); ~SchemaParser() noexcept(false); ParsedSchema parseFromDirectory( const kj::ReadableDirectory& baseDir, kj::Path path, kj::ArrayPtr importPath) const; // Parse a file from the KJ filesystem API. Throws an exception if the file doesn't exist. // // `baseDir` and `path` are used together to resolve relative imports. `path` is the source // file's path within `baseDir`. Relative imports will be interpreted relative to `path` and // will be opened using `baseDir`. Note that the KJ filesystem API prohibits "breaking out" of // a directory using "..", so relative imports will be restricted to children of `baseDir`. // // `importPath` is used for absolute imports (imports that start with a '/'). Each directory in // the array will be searched in order until a file is found. // // All `ReadableDirectory` objects must remain valid until the `SchemaParser` is destroyed. Also, // the `importPath` array must remain valid. `path` will be copied; it need not remain valid. // // This method is a shortcut, equivalent to: // parser.parseFile(SchemaFile::newDiskFile(baseDir, path, importPath))`; // // This method throws an exception if any errors are encountered in the file or in anything the // file depends on. Note that merely importing another file does not count as a dependency on // anything in the imported file -- only the imported types which are actually used are // "dependencies". // // Hint: Use kj::newDiskFilesystem() to initialize the KJ filesystem API. Usually you should do // this at a high level in your program, e.g. the main() function, and then pass down the // appropriate File/Directory objects to the components that need them. Example: // // auto fs = kj::newDiskFilesystem(); // SchemaParser parser; // auto schema = parser.parseFromDirectory(fs->getCurrent(), // kj::Path::parse("foo/bar.capnp"), nullptr); // // Hint: To use in-memory data rather than real disk, you can use kj::newInMemoryDirectory(), // write the files you want, then pass it to SchemaParser. Example: // // auto dir = kj::newInMemoryDirectory(kj::nullClock()); // auto path = kj::Path::parse("foo/bar.capnp"); // dir->openFile(path, kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT) // ->writeAll("struct Foo {}"); // auto schema = parser.parseFromDirectory(*dir, path, nullptr); // // Hint: You can create an in-memory directory but then populate it with real files from disk, // in order to control what is visible while also avoiding reading files yourself or making // extra copies. Example: // // auto fs = kj::newDiskFilesystem(); // auto dir = kj::newInMemoryDirectory(kj::nullClock()); // auto fakePath = kj::Path::parse("foo/bar.capnp"); // auto realPath = kj::Path::parse("path/to/some/file.capnp"); // dir->transfer(fakePath, kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT, // fs->getCurrent(), realPath, kj::TransferMode::LINK); // auto schema = parser.parseFromDirectory(*dir, fakePath, nullptr); // // In this example, note that any imports in the file will fail, since the in-memory directory // you created contains no files except the specific one you linked in. ParsedSchema parseDiskFile(kj::StringPtr displayName, kj::StringPtr diskPath, kj::ArrayPtr importPath) const CAPNP_DEPRECATED("Use parseFromDirectory() instead."); // Creates a private kj::Filesystem and uses it to parse files from the real disk. // // DO NOT USE in new code. Use parseFromDirectory() instead. // // This API has a serious problem: the file can import and embed files located anywhere on disk // using relative paths. Even if you specify no `importPath`, relative imports still work. By // using `parseFromDirectory()`, you can arrange so that imports are only allowed within a // particular directory, or even set up a dummy filesystem where other files are not visible. void setDiskFilesystem(kj::Filesystem& fs) CAPNP_DEPRECATED("Use parseFromDirectory() instead."); // Call before calling parseDiskFile() to choose an alternative disk filesystem implementation. // This exists mostly for testing purposes; new code should use parseFromDirectory() instead. // // If parseDiskFile() is called without having called setDiskFilesystem(), then // kj::newDiskFilesystem() will be used instead. ParsedSchema parseFile(kj::Own&& file) const; // Advanced interface for parsing a file that may or may not be located in any global namespace. // Most users will prefer `parseFromDirectory()`. // // If the file has already been parsed (that is, a SchemaFile that compares equal to this one // was parsed previously), the existing schema will be returned again. // // This method reports errors by calling SchemaFile::reportError() on the file where the error // is located. If that call does not throw an exception, `parseFile()` may in fact return // normally. In this case, the result is a best-effort attempt to compile the schema, but it // may be invalid or corrupt, and using it for anything may cause exceptions to be thrown. kj::Maybe getSourceInfo(Schema schema) const; // Look up source info (e.g. doc comments) for the given schema, which must have come from this // SchemaParser. Note that this will also work for implicit group and param types that don't have // a type name hence don't have a `ParsedSchema`. template inline void loadCompiledTypeAndDependencies() { // See SchemaLoader::loadCompiledTypeAndDependencies(). getLoader().loadCompiledTypeAndDependencies(); } kj::Array getAllLoaded() const { // Gets an array of all schema nodes that have been parsed so far. return getLoader().getAllLoaded(); } void setFileIdsRequired(bool value) { fileIdsRequired = value; } // By befault, capnp files must declare a file-level type ID (like `@0xbe702824338d3f7f;`). // Use `setFileIdsReqired(false)` to lift this requirement. // // If no ID is specified, a random one will be assigned. This will cause all types declared in // the file to have randomized IDs as well (unless they declare an ID explicitly), which means // that parsing the same file twice will appear to to produce a totally new, incompatible set of // types. In particular, this means that you will not be able to use any interface types in the // file for RPC, since the RPC protocol uses type IDs to identify methods. // // Setting this false is particularly useful when using Cap'n Proto as a config format. Typically // type IDs are irrelevant for config files, and the requirement to specify one is cumbersome. // For this reason, `capnp eval` does not require type ID to be present. private: struct Impl; struct DiskFileCompat; class ModuleImpl; kj::Own impl; mutable bool hadErrors = false; bool fileIdsRequired = true; ModuleImpl& getModuleImpl(kj::Own&& file) const; const SchemaLoader& getLoader() const; SchemaLoader& getLoader(); friend class ParsedSchema; }; class ParsedSchema: public Schema { // ParsedSchema is an extension of Schema which also has the ability to look up nested nodes // by name. See `SchemaParser`. class ParsedSchemaList; friend class ParsedSchemaList; public: inline ParsedSchema(): parser(nullptr) {} kj::Maybe findNested(kj::StringPtr name) const; // Gets the nested node with the given name, or returns null if there is no such nested // declaration. ParsedSchema getNested(kj::StringPtr name) const; // Gets the nested node with the given name, or throws an exception if there is no such nested // declaration. ParsedSchemaList getAllNested() const; // Get all the nested nodes schema::Node::SourceInfo::Reader getSourceInfo() const; // Get the source info for this schema. private: inline ParsedSchema(Schema inner, const SchemaParser& parser): Schema(inner), parser(&parser) {} const SchemaParser* parser; friend class SchemaParser; }; class ParsedSchema::ParsedSchemaList { public: ParsedSchemaList() = default; // empty list inline uint size() const { return list.size(); } ParsedSchema operator[](uint index) const; typedef _::IndexingIterator Iterator; inline Iterator begin() const { return Iterator(this, 0); } inline Iterator end() const { return Iterator(this, size()); } private: ParsedSchema parent; List::Reader list; inline ParsedSchemaList(ParsedSchema parent, List::Reader list) : parent(parent), list(list) {} friend class ParsedSchema; }; // ======================================================================================= // Advanced API class SchemaFile { // Abstract interface representing a schema file. You can implement this yourself in order to // gain more control over how the compiler resolves imports and reads files. For the // common case of files on disk or other global filesystem-like namespaces, use // `SchemaFile::newDiskFile()`. public: // Note: Cap'n Proto 0.6.x and below had classes FileReader and DiskFileReader and a method // newDiskFile() defined here. These were removed when SchemaParser was transitioned to use the // KJ filesystem API. You should be able to get the same effect by subclassing // kj::ReadableDirectory, or using kj::newInMemoryDirectory(). static kj::Own newFromDirectory( const kj::ReadableDirectory& baseDir, kj::Path path, kj::ArrayPtr importPath, kj::Maybe displayNameOverride = nullptr); // Construct a SchemaFile representing a file in a kj::ReadableDirectory. This is used to // implement SchemaParser::parseFromDirectory(); see there for details. // // The SchemaFile compares equal to any other SchemaFile that has exactly the same `baseDir` // object (by identity) and `path` (by value). // ----------------------------------------------------------------- // For more control, you can implement this interface. virtual kj::StringPtr getDisplayName() const = 0; // Get the file's name, as it should appear in the schema. virtual kj::Array readContent() const = 0; // Read the file's entire content and return it as a byte array. virtual kj::Maybe> import(kj::StringPtr path) const = 0; // Resolve an import, relative to this file. // // `path` is exactly what appears between quotes after the `import` keyword in the source code. // It is entirely up to the `SchemaFile` to decide how to map this to another file. Typically, // a leading '/' means that the file is an "absolute" path and is searched for in some list of // schema file repositories. On the other hand, a path that doesn't start with '/' is relative // to the importing file. virtual bool operator==(const SchemaFile& other) const = 0; virtual bool operator!=(const SchemaFile& other) const = 0; virtual size_t hashCode() const = 0; // Compare two SchemaFiles to see if they refer to the same underlying file. This is an // optimization used to avoid the need to re-parse a file to check its ID. struct SourcePos { uint byte; uint line; uint column; }; virtual void reportError(SourcePos start, SourcePos end, kj::StringPtr message) const = 0; // Report that the file contains an error at the given interval. private: class DiskSchemaFile; }; } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/arena.h0000644000175000017500000005024314712011043020066 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #ifndef CAPNP_PRIVATE #error "This header is only meant to be included by Cap'n Proto's own source code." #endif #include #include #include #include #include #include "common.h" #include "message.h" #include "layout.h" #include #if !CAPNP_LITE #include "capability.h" #endif // !CAPNP_LITE CAPNP_BEGIN_HEADER namespace capnp { #if !CAPNP_LITE class ClientHook; #endif // !CAPNP_LITE namespace _ { // private class SegmentReader; class SegmentBuilder; class Arena; class BuilderArena; class ReadLimiter; class Segment; typedef kj::Id SegmentId; class ReadLimiter { // Used to keep track of how much data has been processed from a message, and cut off further // processing if and when a particular limit is reached. This is primarily intended to guard // against maliciously-crafted messages which contain cycles or overlapping structures. Cycles // and overlapping are not permitted by the Cap'n Proto format because in many cases they could // be used to craft a deceptively small message which could consume excessive server resources to // process, perhaps even sending it into an infinite loop. Actually detecting overlaps would be // time-consuming, so instead we just keep track of how many words worth of data structures the // receiver has actually dereferenced and error out if this gets too high. // // This counting takes place as you call getters (for non-primitive values) on the message // readers. If you call the same getter twice, the data it returns may be double-counted. This // should not be a big deal in most cases -- just set the read limit high enough that it will // only trigger in unreasonable cases. // // This class is "safe" to use from multiple threads for its intended use case. Threads may // overwrite each others' changes to the counter, but this is OK because it only means that the // limit is enforced a bit less strictly -- it will still kick in eventually. public: inline explicit ReadLimiter(); // No limit. inline explicit ReadLimiter(WordCount64 limit); // Limit to the given number of words. inline void reset(WordCount64 limit); KJ_ALWAYS_INLINE(bool canRead(WordCount64 amount, Arena* arena)); void unread(WordCount64 amount); // Adds back some words to the limit. Useful when the caller knows they are double-reading // some data. private: alignas(8) volatile uint64_t limit; // Current limit, decremented each time catRead() is called. We modify this variable using atomics // with "relaxed" thread safety to make TSAN happy (on ARM & x86 this is no different from a // regular read/write of the variable). See the class comment for why this is OK (previously we // used a regular volatile variable - this is just to make ASAN happy). // // alignas(8) is the default on 64-bit systems, but needed on 32-bit to avoid an expensive // unaligned atomic operation. KJ_DISALLOW_COPY_AND_MOVE(ReadLimiter); KJ_ALWAYS_INLINE(void setLimit(uint64_t newLimit)) { #if defined(__GNUC__) || defined(__clang__) __atomic_store_n(&limit, newLimit, __ATOMIC_RELAXED); #else limit = newLimit; #endif } KJ_ALWAYS_INLINE(uint64_t readLimit() const) { #if defined(__GNUC__) || defined(__clang__) return __atomic_load_n(&limit, __ATOMIC_RELAXED); #else return limit; #endif } }; #if !CAPNP_LITE class BrokenCapFactory { // Callback for constructing broken caps. We use this so that we can avoid arena.c++ having a // link-time dependency on capability code that lives in libcapnp-rpc. public: virtual kj::Own newBrokenCap(kj::StringPtr description) = 0; virtual kj::Own newNullCap() = 0; }; #endif // !CAPNP_LITE class SegmentReader { public: inline SegmentReader(Arena* arena, SegmentId id, const word* ptr, SegmentWordCount size, ReadLimiter* readLimiter); KJ_ALWAYS_INLINE(const word* checkOffset(const word* from, ptrdiff_t offset)); // Adds the given offset to the given pointer, checks that it is still within the bounds of the // segment, then returns it. Note that the "end" pointer of the segment (which technically points // to the word after the last in the segment) is considered in-bounds for this purpose, so you // can't necessarily dereference it. You must call checkObject() next to check that the object // you want to read is entirely in-bounds. // // If `from + offset` is out-of-range, this returns a pointer to the end of the segment. Thus, // any non-zero-sized object will fail `checkObject()`. We do this instead of throwing to save // some code footprint. KJ_ALWAYS_INLINE(bool checkObject(const word* start, WordCountN<31> size)); // Assuming that `start` is in-bounds for this segment (probably checked using `checkOffset()`), // check that `start + size` is also in-bounds, and hence the whole area in-between is valid. KJ_ALWAYS_INLINE(bool amplifiedRead(WordCount virtualAmount)); // Indicates that the reader should pretend that `virtualAmount` additional data was read even // though no actual pointer was traversed. This is used e.g. when reading a struct list pointer // where the element sizes are zero -- the sender could set the list size arbitrarily high and // cause the receiver to iterate over this list even though the message itself is small, so we // need to defend against DoS attacks based on this. inline Arena* getArena(); inline SegmentId getSegmentId(); inline const word* getStartPtr(); inline SegmentWordCount getOffsetTo(const word* ptr); inline SegmentWordCount getSize(); inline kj::ArrayPtr getArray(); inline void unread(WordCount64 amount); // Add back some words to the ReadLimiter. private: Arena* arena; SegmentId id; kj::ArrayPtr ptr; // size guaranteed to fit in SEGMENT_WORD_COUNT_BITS bits ReadLimiter* readLimiter; KJ_DISALLOW_COPY_AND_MOVE(SegmentReader); friend class SegmentBuilder; [[noreturn]] static void abortCheckObjectFault(); // Called in debug mode in cases that would segfault in opt mode. (Should be impossible!) }; class SegmentBuilder: public SegmentReader { public: inline SegmentBuilder(BuilderArena* arena, SegmentId id, word* ptr, SegmentWordCount size, ReadLimiter* readLimiter, SegmentWordCount wordsUsed = ZERO * WORDS); inline SegmentBuilder(BuilderArena* arena, SegmentId id, const word* ptr, SegmentWordCount size, ReadLimiter* readLimiter); inline SegmentBuilder(BuilderArena* arena, SegmentId id, decltype(nullptr), ReadLimiter* readLimiter); KJ_ALWAYS_INLINE(word* allocate(SegmentWordCount amount)); KJ_ALWAYS_INLINE(void checkWritable()); // Throw an exception if the segment is read-only (meaning it is a reference to external data). KJ_ALWAYS_INLINE(word* getPtrUnchecked(SegmentWordCount offset)); // Get a writable pointer into the segment. Throws an exception if the segment is read-only (i.e. // a reference to external immutable data). inline BuilderArena* getArena(); inline kj::ArrayPtr currentlyAllocated(); inline void reset(); inline bool isWritable() { return !readOnly; } inline void tryTruncate(word* from, word* to); // If `from` points just past the current end of the segment, then move the end back to `to`. // Otherwise, do nothing. inline bool tryExtend(word* from, word* to); // If `from` points just past the current end of the segment, and `to` is within the segment // boundaries, then move the end up to `to` and return true. Otherwise, do nothing and return // false. private: word* pos; // Pointer to a pointer to the current end point of the segment, i.e. the location where the // next object should be allocated. bool readOnly; [[noreturn]] void throwNotWritable(); KJ_DISALLOW_COPY_AND_MOVE(SegmentBuilder); }; class Arena { public: virtual ~Arena() noexcept(false); virtual SegmentReader* tryGetSegment(SegmentId id) = 0; // Gets the segment with the given ID, or return nullptr if no such segment exists. virtual void reportReadLimitReached() = 0; // Called to report that the read limit has been reached. See ReadLimiter, below. This invokes // the VALIDATE_INPUT() macro which may throw an exception; if it returns normally, the caller // will need to continue with default values. }; class ReaderArena final: public Arena { public: explicit ReaderArena(MessageReader* message); ~ReaderArena() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(ReaderArena); size_t sizeInWords(); // implements Arena ------------------------------------------------ SegmentReader* tryGetSegment(SegmentId id) override; void reportReadLimitReached() override; private: MessageReader* message; ReadLimiter readLimiter; // Optimize for single-segment messages so that small messages are handled quickly. SegmentReader segment0; typedef kj::HashMap> SegmentMap; kj::MutexGuarded> moreSegments; // We need to mutex-guard the segment map because we lazily initialize segments when they are // first requested, but a Reader is allowed to be used concurrently in multiple threads. Luckily // this only applies to large messages. // // TODO(perf): Thread-local thing instead? Some kind of lockless map? Or do sharing of data // in a different way, where you have to construct a new MessageReader in each thread (but // possibly backed by the same data)? ReaderArena(MessageReader* message, kj::ArrayPtr firstSegment); ReaderArena(MessageReader* message, const word* firstSegment, SegmentWordCount firstSegmentSize); }; class BuilderArena final: public Arena { // A BuilderArena that does not allow the injection of capabilities. public: explicit BuilderArena(MessageBuilder* message); BuilderArena(MessageBuilder* message, kj::ArrayPtr segments); ~BuilderArena() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(BuilderArena); size_t sizeInWords(); inline SegmentBuilder* getRootSegment() { return &segment0; } kj::ArrayPtr> getSegmentsForOutput(); // Get an array of all the segments, suitable for writing out. This only returns the allocated // portion of each segment, whereas tryGetSegment() returns something that includes // not-yet-allocated space. inline CapTableBuilder* getLocalCapTable() { // Return a CapTableBuilder that merely implements local loopback. That is, you can set // capabilities, then read the same capabilities back, but there is no intent ever to transmit // these capabilities. A MessageBuilder that isn't imbued with some other CapTable uses this // by default. // // TODO(cleanup): It's sort of a hack that this exists. In theory, perhaps, unimbued // MessageBuilders should throw exceptions on any attempt to access capability fields, like // unimbued MessageReaders do. However, lots of code exists which uses MallocMessageBuilder // as a temporary holder for data to be copied in and out (without being serialized), and it // is expected that such data can include capabilities, which is admittedly reasonable. // Therefore, all MessageBuilders must have a cap table by default. Arguably we should // deprecate this usage and instead define a new helper type for this exact purpose. return &localCapTable; } kj::Own<_::CapTableBuilder> releaseLocalCapTable() { return kj::heap(kj::mv(localCapTable)); } SegmentBuilder* getSegment(SegmentId id); // Get the segment with the given id. Crashes or throws an exception if no such segment exists. struct AllocateResult { SegmentBuilder* segment; word* words; }; AllocateResult allocate(SegmentWordCount amount); // Find a segment with at least the given amount of space available and allocate the space. // Note that allocating directly from a particular segment is much faster, but allocating from // the arena is guaranteed to succeed. Therefore callers should try to allocate from a specific // segment first if there is one, then fall back to the arena. SegmentBuilder* addExternalSegment(kj::ArrayPtr content); // Add a new segment to the arena which points to some existing memory region. The segment is // assumed to be completley full; the arena will never allocate from it. In fact, the segment // is considered read-only. Any attempt to get a Builder pointing into this segment will throw // an exception. Readers are allowed, however. // // This can be used to inject some external data into a message without a copy, e.g. embedding a // large mmap'd file into a message as `Data` without forcing that data to actually be read in // from disk (until the message itself is written out). `Orphanage` provides the public API for // this feature. // implements Arena ------------------------------------------------ SegmentReader* tryGetSegment(SegmentId id) override; void reportReadLimitReached() override; private: MessageBuilder* message; ReadLimiter dummyLimiter; class LocalCapTable final: public CapTableBuilder { public: kj::Maybe> extractCap(uint index) override; uint injectCap(kj::Own&& cap) override; void dropCap(uint index) override; #if !CAPNP_LITE private: kj::Vector>> capTable; #endif // ! CAPNP_LITE }; LocalCapTable localCapTable; SegmentBuilder segment0; kj::ArrayPtr segment0ForOutput; struct MultiSegmentState { kj::Vector> builders; kj::Vector> forOutput; }; kj::Maybe> moreSegments; SegmentBuilder* segmentWithSpace = nullptr; // When allocating, look for space in this segment first before resorting to allocating a new // segment. This is not necessarily the last segment because addExternalSegment() may add a // segment that is already-full, in which case we don't update this pointer. template // Can be `word` or `const word`. SegmentBuilder* addSegmentInternal(kj::ArrayPtr content); }; // ======================================================================================= inline ReadLimiter::ReadLimiter() : limit(kj::maxValue) {} inline ReadLimiter::ReadLimiter(WordCount64 limit): limit(unbound(limit / WORDS)) {} inline void ReadLimiter::reset(WordCount64 limit) { setLimit(unbound(limit / WORDS)); } inline bool ReadLimiter::canRead(WordCount64 amount, Arena* arena) { // Be careful not to store an underflowed value into `limit`, even if multiple threads are // decrementing it. uint64_t current = readLimit(); if (KJ_UNLIKELY(unbound(amount / WORDS) > current)) { arena->reportReadLimitReached(); return false; } else { setLimit(current - unbound(amount / WORDS)); return true; } } // ------------------------------------------------------------------- inline SegmentReader::SegmentReader(Arena* arena, SegmentId id, const word* ptr, SegmentWordCount size, ReadLimiter* readLimiter) : arena(arena), id(id), ptr(kj::arrayPtr(ptr, unbound(size / WORDS))), readLimiter(readLimiter) {} inline const word* SegmentReader::checkOffset(const word* from, ptrdiff_t offset) { ptrdiff_t min = ptr.begin() - from; ptrdiff_t max = ptr.end() - from; if (offset >= min && offset <= max) { return from + offset; } else { return ptr.end(); } } inline bool SegmentReader::checkObject(const word* start, WordCountN<31> size) { auto startOffset = intervalLength(ptr.begin(), start, MAX_SEGMENT_WORDS); #ifdef KJ_DEBUG if (startOffset > bounded(ptr.size()) * WORDS) { abortCheckObjectFault(); } #endif return startOffset + size <= bounded(ptr.size()) * WORDS && readLimiter->canRead(size, arena); } inline bool SegmentReader::amplifiedRead(WordCount virtualAmount) { return readLimiter->canRead(virtualAmount, arena); } inline Arena* SegmentReader::getArena() { return arena; } inline SegmentId SegmentReader::getSegmentId() { return id; } inline const word* SegmentReader::getStartPtr() { return ptr.begin(); } inline SegmentWordCount SegmentReader::getOffsetTo(const word* ptr) { KJ_IREQUIRE(this->ptr.begin() <= ptr && ptr <= this->ptr.end()); return intervalLength(this->ptr.begin(), ptr, MAX_SEGMENT_WORDS); } inline SegmentWordCount SegmentReader::getSize() { return assumeBits(ptr.size()) * WORDS; } inline kj::ArrayPtr SegmentReader::getArray() { return ptr; } inline void SegmentReader::unread(WordCount64 amount) { readLimiter->unread(amount); } // ------------------------------------------------------------------- inline SegmentBuilder::SegmentBuilder( BuilderArena* arena, SegmentId id, word* ptr, SegmentWordCount size, ReadLimiter* readLimiter, SegmentWordCount wordsUsed) : SegmentReader(arena, id, ptr, size, readLimiter), pos(ptr + wordsUsed), readOnly(false) {} inline SegmentBuilder::SegmentBuilder( BuilderArena* arena, SegmentId id, const word* ptr, SegmentWordCount size, ReadLimiter* readLimiter) : SegmentReader(arena, id, ptr, size, readLimiter), // const_cast is safe here because the member won't ever be dereferenced because it appears // to point to the end of the segment anyway. pos(const_cast(ptr + size)), readOnly(true) {} inline SegmentBuilder::SegmentBuilder(BuilderArena* arena, SegmentId id, decltype(nullptr), ReadLimiter* readLimiter) : SegmentReader(arena, id, nullptr, ZERO * WORDS, readLimiter), pos(nullptr), readOnly(false) {} inline word* SegmentBuilder::allocate(SegmentWordCount amount) { if (intervalLength(pos, ptr.end(), MAX_SEGMENT_WORDS) < amount) { // Not enough space in the segment for this allocation. return nullptr; } else { // Success. word* result = pos; pos = pos + amount; return result; } } inline void SegmentBuilder::checkWritable() { if (KJ_UNLIKELY(readOnly)) throwNotWritable(); } inline word* SegmentBuilder::getPtrUnchecked(SegmentWordCount offset) { return const_cast(ptr.begin() + offset); } inline BuilderArena* SegmentBuilder::getArena() { // Down-cast safe because SegmentBuilder's constructor always initializes its SegmentReader base // class with an Arena pointer that actually points to a BuilderArena. return static_cast(arena); } inline kj::ArrayPtr SegmentBuilder::currentlyAllocated() { return kj::arrayPtr(ptr.begin(), pos - ptr.begin()); } inline void SegmentBuilder::reset() { word* start = getPtrUnchecked(ZERO * WORDS); memset(start, 0, (pos - start) * sizeof(word)); pos = start; } inline void SegmentBuilder::tryTruncate(word* from, word* to) { if (pos == from) pos = to; } inline bool SegmentBuilder::tryExtend(word* from, word* to) { // Careful about overflow. if (pos == from && to <= ptr.end() && to >= from) { pos = to; return true; } else { return false; } } } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/serialize-test.c++0000644000175000017500000003541514712011043022071 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "serialize.h" #include #include #include #include #include #include #include "test-util.h" namespace capnp { namespace _ { // private namespace { class TestMessageBuilder: public MallocMessageBuilder { // A MessageBuilder that tries to allocate an exact number of total segments, by allocating // minimum-size segments until it reaches the number, then allocating one large segment to // finish. public: explicit TestMessageBuilder(uint desiredSegmentCount) : MallocMessageBuilder(0, AllocationStrategy::FIXED_SIZE), desiredSegmentCount(desiredSegmentCount) {} ~TestMessageBuilder() { EXPECT_EQ(0u, desiredSegmentCount); } kj::ArrayPtr allocateSegment(uint minimumSize) override { if (desiredSegmentCount <= 1) { if (desiredSegmentCount < 1) { ADD_FAILURE() << "Allocated more segments than desired."; } else { --desiredSegmentCount; } return MallocMessageBuilder::allocateSegment(SUGGESTED_FIRST_SEGMENT_WORDS); } else { --desiredSegmentCount; return MallocMessageBuilder::allocateSegment(minimumSize); } } private: uint desiredSegmentCount; }; kj::Array copyWords(kj::ArrayPtr input) { auto result = kj::heapArray(input.size()); memcpy(result.asBytes().begin(), input.asBytes().begin(), input.asBytes().size()); return result; } TEST(Serialize, FlatArray) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); { FlatArrayMessageReader reader(serialized.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serialized.end(), reader.getEnd()); } { MallocMessageBuilder builder2; auto remaining = initMessageBuilderFromFlatArrayCopy(serialized, builder2); checkTestMessage(builder2.getRoot()); EXPECT_EQ(serialized.end(), remaining.begin()); EXPECT_EQ(serialized.end(), remaining.end()); } kj::Array serializedWithSuffix = kj::heapArray(serialized.size() + 5); memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word)); { FlatArrayMessageReader reader(serializedWithSuffix.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd()); } { MallocMessageBuilder builder2; auto remaining = initMessageBuilderFromFlatArrayCopy(serializedWithSuffix, builder2); checkTestMessage(builder2.getRoot()); EXPECT_EQ(serializedWithSuffix.end() - 5, remaining.begin()); EXPECT_EQ(serializedWithSuffix.end(), remaining.end()); } { // Test expectedSizeInWordsFromPrefix(). We pass in a copy of the slice so that valgrind can // detect out-of-bounds access. EXPECT_EQ(1, expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, 0)))); for (uint i = 1; i <= serialized.size(); i++) { EXPECT_EQ(serialized.size(), expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, i)))); } } } TEST(Serialize, FlatArrayOddSegmentCount) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); { FlatArrayMessageReader reader(serialized.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serialized.end(), reader.getEnd()); } kj::Array serializedWithSuffix = kj::heapArray(serialized.size() + 5); memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word)); { FlatArrayMessageReader reader(serializedWithSuffix.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd()); } { // Test expectedSizeInWordsFromPrefix(). We pass in a copy of the slice so that valgrind can // detect out-of-bounds access. // Segment table is 4 words, so with fewer words we'll have incomplete information. for (uint i = 0; i < 4; i++) { size_t expectedSize = expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, i))); EXPECT_LT(expectedSize, serialized.size()); EXPECT_GT(expectedSize, i); } // After that, we get the exact length. for (uint i = 4; i <= serialized.size(); i++) { EXPECT_EQ(serialized.size(), expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, i)))); } } } TEST(Serialize, FlatArrayEvenSegmentCount) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); { FlatArrayMessageReader reader(serialized.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serialized.end(), reader.getEnd()); } kj::Array serializedWithSuffix = kj::heapArray(serialized.size() + 5); memcpy(serializedWithSuffix.begin(), serialized.begin(), serialized.size() * sizeof(word)); { FlatArrayMessageReader reader(serializedWithSuffix.asPtr()); checkTestMessage(reader.getRoot()); EXPECT_EQ(serializedWithSuffix.end() - 5, reader.getEnd()); } { // Test expectedSizeInWordsFromPrefix(). We pass in a copy of the slice so that valgrind can // detect out-of-bounds access. // Segment table is 6 words, so with fewer words we'll have incomplete information. for (uint i = 0; i < 6; i++) { size_t expectedSize = expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, i))); EXPECT_LT(expectedSize, serialized.size()); EXPECT_GT(expectedSize, i); } // After that, we get the exact length. for (uint i = 6; i <= serialized.size(); i++) { EXPECT_EQ(serialized.size(), expectedSizeInWordsFromPrefix(copyWords(serialized.slice(0, i)))); } } } class TestInputStream: public kj::InputStream { public: TestInputStream(kj::ArrayPtr data, bool lazy) : pos(data.asChars().begin()), end(data.asChars().end()), lazy(lazy) {} ~TestInputStream() {} size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override { KJ_ASSERT(maxBytes <= size_t(end - pos), "Overran end of stream."); size_t amount = lazy ? minBytes : maxBytes; memcpy(buffer, pos, amount); pos += amount; return amount; } private: const char* pos; const char* end; bool lazy; }; TEST(Serialize, InputStream) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), false); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamScratchSpace) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); word scratch[4096]; TestInputStream stream(serialized.asPtr(), false); InputStreamMessageReader reader(stream, ReaderOptions(), kj::ArrayPtr(scratch, 4096)); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamLazy) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), true); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamOddSegmentCount) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), false); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamOddSegmentCountLazy) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), true); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamEvenSegmentCount) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), false); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamEvenSegmentCountLazy) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), true); InputStreamMessageReader reader(stream, ReaderOptions()); checkTestMessage(reader.getRoot()); } TEST(Serialize, InputStreamToBuilder) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestInputStream stream(serialized.asPtr(), false); MallocMessageBuilder builder2; readMessageCopy(stream, builder2); checkTestMessage(builder2.getRoot()); } class TestOutputStream: public kj::OutputStream { public: TestOutputStream() {} ~TestOutputStream() {} void write(const void* buffer, size_t size) override { data.append(reinterpret_cast(buffer), size); } bool dataEquals(kj::ArrayPtr other) { return data == std::string(other.asChars().begin(), other.asChars().size()); } private: std::string data; }; TEST(Serialize, WriteMessage) { TestMessageBuilder builder(1); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestOutputStream output; writeMessage(output, builder); EXPECT_TRUE(output.dataEquals(serialized.asPtr())); } TEST(Serialize, WriteMessageOddSegmentCount) { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestOutputStream output; writeMessage(output, builder); EXPECT_TRUE(output.dataEquals(serialized.asPtr())); } TEST(Serialize, WriteMessageEvenSegmentCount) { TestMessageBuilder builder(10); initTestMessage(builder.initRoot()); kj::Array serialized = messageToFlatArray(builder); TestOutputStream output; writeMessage(output, builder); EXPECT_TRUE(output.dataEquals(serialized.asPtr())); } #if _WIN32 int mkstemp(char *tpl) { char* end = tpl + strlen(tpl); while (end > tpl && *(end-1) == 'X') --end; for (;;) { KJ_ASSERT(_mktemp(tpl) == tpl); int fd = open(tpl, O_RDWR | O_CREAT | O_EXCL | O_TEMPORARY | O_BINARY, 0700); if (fd >= 0) { return fd; } int error = errno; if (error != EEXIST && error != EINTR) { KJ_FAIL_SYSCALL("open(mktemp())", error, tpl); } memset(end, 'X', strlen(end)); } } #endif TEST(Serialize, FileDescriptors) { #if _WIN32 || __ANDROID__ // TODO(cleanup): Find the Windows temp directory? Seems overly difficult. char filename[] = "capnproto-serialize-test-XXXXXX"; #else char filename[] = "/tmp/capnproto-serialize-test-XXXXXX"; #endif kj::AutoCloseFd tmpfile(mkstemp(filename)); ASSERT_GE(tmpfile.get(), 0); #if !_WIN32 // Unlink the file so that it will be deleted on close. // (For win32, we already handled this is mkstemp().) EXPECT_EQ(0, unlink(filename)); #endif { TestMessageBuilder builder(7); initTestMessage(builder.initRoot()); writeMessageToFd(tmpfile.get(), builder); } { TestMessageBuilder builder(1); builder.initRoot().setTextField("second message in file"); writeMessageToFd(tmpfile.get(), builder); } lseek(tmpfile, 0, SEEK_SET); { StreamFdMessageReader reader(tmpfile.get()); checkTestMessage(reader.getRoot()); } { StreamFdMessageReader reader(tmpfile.get()); EXPECT_EQ("second message in file", reader.getRoot().getTextField()); } } TEST(Serialize, RejectTooManySegments) { kj::Array data = kj::heapArray(8192); WireValue* table = reinterpret_cast*>(data.begin()); table[0].set(1024); for (uint i = 0; i < 1024; i++) { table[i+1].set(1); } TestInputStream input(data.asPtr(), false); kj::Maybe e = kj::runCatchingExceptions([&]() { InputStreamMessageReader reader(input); #if !KJ_NO_EXCEPTIONS ADD_FAILURE() << "Should have thrown an exception."; #endif }); KJ_EXPECT(e != nullptr, "Should have thrown an exception."); } #if !__MINGW32__ // Inexplicably crashes when exception is thrown from constructor. TEST(Serialize, RejectHugeMessage) { // A message whose root struct contains two words of data! AlignedData<4> data = {{0,0,0,0,3,0,0,0, 0,0,0,0,2,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}}; TestInputStream input(kj::arrayPtr(data.words, 4), false); // We'll set the traversal limit to 2 words so our 3-word message is too big. ReaderOptions options; options.traversalLimitInWords = 2; kj::Maybe e = kj::runCatchingExceptions([&]() { InputStreamMessageReader reader(input, options); #if !KJ_NO_EXCEPTIONS ADD_FAILURE() << "Should have thrown an exception."; #endif }); KJ_EXPECT(e != nullptr, "Should have thrown an exception."); } #endif // !__MINGW32__ // TODO(test): Test error cases. } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/message-test.c++0000644000175000017500000001711414527152321021533 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "message.h" #include "test-util.h" #include #include #include #include namespace capnp { namespace _ { // private namespace { TEST(Message, MallocBuilderWithFirstSegment) { word scratch[16]; memset(scratch, 0, sizeof(scratch)); MallocMessageBuilder builder(kj::arrayPtr(scratch, 16), AllocationStrategy::FIXED_SIZE); kj::ArrayPtr segment = builder.allocateSegment(1); EXPECT_EQ(scratch, segment.begin()); EXPECT_EQ(16u, segment.size()); segment = builder.allocateSegment(1); EXPECT_NE(scratch, segment.begin()); EXPECT_EQ(16u, segment.size()); segment = builder.allocateSegment(1); EXPECT_NE(scratch, segment.begin()); EXPECT_EQ(16u, segment.size()); } class TestInitMessageBuilder: public MessageBuilder { public: TestInitMessageBuilder(kj::ArrayPtr segments): MessageBuilder(segments) {} kj::ArrayPtr allocateSegment(uint minimumSize) override { auto array = kj::heapArray(minimumSize); memset(array.begin(), 0, array.asBytes().size()); allocations.add(kj::mv(array)); return allocations.back(); } kj::Vector> allocations; }; TEST(Message, MessageBuilderInit) { MallocMessageBuilder builder(2048); initTestMessage(builder.getRoot()); // Pull the segments out and make a segment init table out of them. // // We const_cast for simplicity of implementing the test, but you shouldn't do that at home. :) auto segs = builder.getSegmentsForOutput(); ASSERT_EQ(1, segs.size()); auto segInits = KJ_MAP(seg, segs) -> MessageBuilder::SegmentInit { return { kj::arrayPtr(const_cast(seg.begin()), seg.size()), seg.size() }; }; // Init a new builder from the old segments. TestInitMessageBuilder builder2(segInits); checkTestMessage(builder2.getRoot()); // Verify that they're really using the same underlying memory. builder2.getRoot().setInt64Field(123321); EXPECT_EQ(123321, builder.getRoot().getInt64Field()); // Force builder2 to allocate new space. EXPECT_EQ(0, builder2.allocations.size()); builder2.getRoot().setTextField("foobarbaz"); EXPECT_EQ(1, builder2.allocations.size()); } TEST(Message, MessageBuilderInitMultiSegment) { // Same as previous test, but with a message containing many segments. MallocMessageBuilder builder(1, AllocationStrategy::FIXED_SIZE); initTestMessage(builder.getRoot()); // Pull the segments out and make a segment init table out of them. // // We const_cast for simplicity of implementing the test, but you shouldn't do that at home. :) auto segs = builder.getSegmentsForOutput(); ASSERT_NE(1, segs.size()); auto segInits = KJ_MAP(seg, segs) -> MessageBuilder::SegmentInit { return { kj::arrayPtr(const_cast(seg.begin()), seg.size()), seg.size() }; }; // Init a new builder from the old segments. TestInitMessageBuilder builder2(segInits); checkTestMessage(builder2.getRoot()); // Verify that they're really using the same underlying memory. builder2.getRoot().setInt64Field(123321); EXPECT_EQ(123321, builder.getRoot().getInt64Field()); // Force builder2 to allocate new space. EXPECT_EQ(0, builder2.allocations.size()); builder2.getRoot().setTextField("foobarbaz"); EXPECT_EQ(1, builder2.allocations.size()); } TEST(Message, MessageBuilderInitSpaceAvailable) { word buffer[2048]; memset(buffer, 0, sizeof(buffer)); MallocMessageBuilder builder(buffer); initTestMessage(builder.getRoot()); // Find out how much space in `buffer` was used in order to use in initializing the new message. auto segs = builder.getSegmentsForOutput(); ASSERT_EQ(1, segs.size()); KJ_ASSERT(segs[0].begin() == buffer); MessageBuilder::SegmentInit init = { kj::ArrayPtr(buffer), segs[0].size() }; // Init a new builder from the old segments. TestInitMessageBuilder builder2(kj::arrayPtr(&init, 1)); checkTestMessage(builder2.getRoot()); // Verify that they're really using the same underlying memory. builder2.getRoot().setInt64Field(123321); EXPECT_EQ(123321, builder.getRoot().getInt64Field()); // Ask builder2 to allocate new space. It should go into the free space at the end of the // segment. EXPECT_EQ(0, builder2.allocations.size()); builder2.getRoot().setTextField("foobarbaz"); EXPECT_EQ(0, builder2.allocations.size()); EXPECT_EQ(kj::implicitCast(buffer + segs[0].size()), kj::implicitCast(builder2.getRoot().getTextField().begin())); } TEST(Message, ReadWriteDataStruct) { MallocMessageBuilder builder; auto root = builder.getRoot(); root.setUInt32Field(123); root.setFloat64Field(1.5); root.setTextField("foo"); auto copy = readDataStruct(writeDataStruct(root)); EXPECT_EQ(123, copy.getUInt32Field()); EXPECT_EQ(1.5, copy.getFloat64Field()); EXPECT_FALSE(copy.hasTextField()); checkTestMessageAllZero(readDataStruct(nullptr)); checkTestMessageAllZero(defaultValue()); } KJ_TEST("clone()") { MallocMessageBuilder builder(2048); initTestMessage(builder.getRoot()); auto copy = clone(builder.getRoot().asReader()); checkTestMessage(*copy); } #if !CAPNP_ALLOW_UNALIGNED KJ_TEST("disallow unaligned") { union { char buffer[16]; word align; }; memset(buffer, 0, sizeof(buffer)); auto unaligned = kj::arrayPtr(reinterpret_cast(buffer + 1), 1); kj::ArrayPtr segments[1] = {unaligned}; SegmentArrayMessageReader message(segments); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("unaligned", message.getRoot()); } #endif KJ_TEST("MessageBuilder::sizeInWords()") { capnp::MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); size_t expected = root.totalSize().wordCount + 1; KJ_EXPECT(builder.sizeInWords() == expected); auto segments = builder.getSegmentsForOutput(); size_t total = 0; for (auto& segment: segments) { total += segment.size(); } KJ_EXPECT(total == expected); capnp::SegmentArrayMessageReader reader(segments); checkTestMessage(reader.getRoot()); KJ_EXPECT(reader.sizeInWords() == expected); } // TODO(test): More tests. } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/dynamic-capability.c++0000644000175000017500000001100714712011043022657 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file contains the parts of dynamic.h that live in capnp-rpc.so. #include "dynamic.h" #include namespace capnp { DynamicCapability::Client DynamicCapability::Client::upcast(InterfaceSchema requestedSchema) { KJ_REQUIRE(schema.extends(requestedSchema), "Can't upcast to non-superclass.") {} return DynamicCapability::Client(requestedSchema, hook->addRef()); } Request DynamicCapability::Client::newRequest( InterfaceSchema::Method method, kj::Maybe sizeHint) { auto methodInterface = method.getContainingInterface(); KJ_REQUIRE(schema.extends(methodInterface), "Interface does not implement this method."); auto paramType = method.getParamType(); auto resultType = method.getResultType(); CallHints hints; hints.noPromisePipelining = !resultType.mayContainCapabilities(); auto typeless = hook->newCall( methodInterface.getProto().getId(), method.getIndex(), sizeHint, hints); return Request( typeless.getAs(paramType), kj::mv(typeless.hook), resultType); } Request DynamicCapability::Client::newRequest( kj::StringPtr methodName, kj::Maybe sizeHint) { return newRequest(schema.getMethodByName(methodName), sizeHint); } Capability::Server::DispatchCallResult DynamicCapability::Server::dispatchCall( uint64_t interfaceId, uint16_t methodId, CallContext context) { KJ_IF_MAYBE(interface, schema.findSuperclass(interfaceId)) { auto methods = interface->getMethods(); if (methodId < methods.size()) { auto method = methods[methodId]; auto resultType = method.getResultType(); return { call(method, CallContext(*context.hook, method.getParamType(), resultType)), resultType.isStreamResult(), options.allowCancellation }; } else { return internalUnimplemented( interface->getProto().getDisplayName().cStr(), interfaceId, methodId); } } else { return internalUnimplemented(schema.getProto().getDisplayName().cStr(), interfaceId); } } RemotePromise Request::send() { auto typelessPromise = hook->send(); hook = nullptr; // prevent reuse auto resultSchemaCopy = resultSchema; // Convert the Promise to return the correct response type. // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the // Pipeline part of the RemotePromise. auto typedPromise = kj::implicitCast>&>(typelessPromise) .then([=](Response&& response) -> Response { return Response(response.getAs(resultSchemaCopy), kj::mv(response.hook)); }); // Wrap the typeless pipeline in a typed wrapper. DynamicStruct::Pipeline typedPipeline(resultSchema, kj::mv(kj::implicitCast(typelessPromise))); return RemotePromise(kj::mv(typedPromise), kj::mv(typedPipeline)); } kj::Promise Request::sendStreaming() { KJ_REQUIRE(resultSchema.isStreamResult()); auto promise = hook->sendStreaming(); hook = nullptr; // prevent reuse return promise; } } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema.capnp.c++0000644000175000017500000055730314731420004021474 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: schema.capnp #include "schema.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<225> b_e682ab4cf923a417 = { { 0, 0, 0, 0, 5, 0, 6, 0, 23, 164, 35, 249, 76, 171, 130, 230, 13, 0, 0, 0, 1, 0, 5, 0, 217, 114, 76, 98, 9, 197, 63, 169, 6, 0, 7, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 146, 0, 0, 0, 29, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 23, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 1, 0, 1, 0, 177, 163, 15, 241, 204, 27, 82, 185, 17, 0, 0, 0, 82, 0, 0, 0, 66, 194, 15, 250, 187, 85, 191, 222, 17, 0, 0, 0, 90, 0, 0, 0, 174, 87, 19, 4, 227, 29, 142, 243, 17, 0, 0, 0, 90, 0, 0, 0, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 0, 0, 0, 0, 0, 78, 101, 115, 116, 101, 100, 78, 111, 100, 101, 0, 0, 0, 0, 0, 0, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 1, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 1, 0, 0, 3, 0, 1, 0, 128, 1, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 1, 0, 0, 3, 0, 1, 0, 136, 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 1, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 1, 0, 0, 3, 0, 1, 0, 148, 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 1, 0, 0, 3, 0, 1, 0, 152, 1, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 0, 0, 3, 0, 1, 0, 176, 1, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 1, 0, 0, 3, 0, 1, 0, 200, 1, 0, 0, 2, 0, 1, 0, 8, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 1, 0, 0, 3, 0, 1, 0, 204, 1, 0, 0, 2, 0, 1, 0, 9, 0, 254, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 53, 68, 251, 55, 155, 177, 160, 158, 201, 1, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 253, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 152, 245, 51, 67, 54, 179, 74, 181, 177, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 252, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 143, 33, 194, 240, 207, 83, 39, 232, 153, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 251, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32, 148, 13, 122, 172, 165, 138, 177, 133, 1, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 250, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 144, 2, 10, 64, 212, 25, 22, 236, 109, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 1, 0, 0, 3, 0, 1, 0, 116, 1, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 32, 1, 0, 0, 0, 0, 1, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 1, 0, 0, 3, 0, 1, 0, 124, 1, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 80, 114, 101, 102, 105, 120, 76, 101, 110, 103, 116, 104, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 111, 112, 101, 73, 100, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 101, 115, 116, 101, 100, 78, 111, 100, 101, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 66, 194, 15, 250, 187, 85, 191, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 66, 117, 37, 171, 13, 149, 200, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 117, 99, 116, 0, 0, 101, 110, 117, 109, 0, 0, 0, 0, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 99, 111, 110, 115, 116, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 177, 163, 15, 241, 204, 27, 82, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 115, 71, 101, 110, 101, 114, 105, 99, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e682ab4cf923a417 = b_e682ab4cf923a417.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_e682ab4cf923a417[] = { &s_9ea0b19b37fb4435, &s_b18aa5ac7a0d9420, &s_b54ab3364333f598, &s_b9521bccf10fa3b1, &s_debf55bbfa0fc242, &s_e82753cff0c2218f, &s_ec1619d4400a0290, &s_f1c8950dab257542, }; static const uint16_t m_e682ab4cf923a417[] = {11, 5, 10, 1, 2, 8, 6, 0, 9, 13, 4, 12, 3, 7}; static const uint16_t i_e682ab4cf923a417[] = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 12, 13}; const ::capnp::_::RawSchema s_e682ab4cf923a417 = { 0xe682ab4cf923a417, b_e682ab4cf923a417.words, 225, d_e682ab4cf923a417, m_e682ab4cf923a417, 8, 14, i_e682ab4cf923a417, nullptr, nullptr, { &s_e682ab4cf923a417, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<33> b_b9521bccf10fa3b1 = { { 0, 0, 0, 0, 5, 0, 6, 0, 177, 163, 15, 241, 204, 27, 82, 185, 18, 0, 0, 0, 1, 0, 0, 0, 23, 164, 35, 249, 76, 171, 130, 230, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b9521bccf10fa3b1 = b_b9521bccf10fa3b1.words; #if !CAPNP_LITE static const uint16_t m_b9521bccf10fa3b1[] = {0}; static const uint16_t i_b9521bccf10fa3b1[] = {0}; const ::capnp::_::RawSchema s_b9521bccf10fa3b1 = { 0xb9521bccf10fa3b1, b_b9521bccf10fa3b1.words, 33, nullptr, m_b9521bccf10fa3b1, 0, 1, i_b9521bccf10fa3b1, nullptr, nullptr, { &s_b9521bccf10fa3b1, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<48> b_debf55bbfa0fc242 = { { 0, 0, 0, 0, 5, 0, 6, 0, 66, 194, 15, 250, 187, 85, 191, 222, 18, 0, 0, 0, 1, 0, 1, 0, 23, 164, 35, 249, 76, 171, 130, 230, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 78, 101, 115, 116, 101, 100, 78, 111, 100, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_debf55bbfa0fc242 = b_debf55bbfa0fc242.words; #if !CAPNP_LITE static const uint16_t m_debf55bbfa0fc242[] = {1, 0}; static const uint16_t i_debf55bbfa0fc242[] = {0, 1}; const ::capnp::_::RawSchema s_debf55bbfa0fc242 = { 0xdebf55bbfa0fc242, b_debf55bbfa0fc242.words, 48, nullptr, m_debf55bbfa0fc242, 0, 2, i_debf55bbfa0fc242, nullptr, nullptr, { &s_debf55bbfa0fc242, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<102> b_f38e1de3041357ae = { { 0, 0, 0, 0, 5, 0, 6, 0, 174, 87, 19, 4, 227, 29, 142, 243, 18, 0, 0, 0, 1, 0, 2, 0, 23, 164, 35, 249, 76, 171, 130, 230, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 33, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 162, 31, 142, 137, 56, 144, 186, 194, 1, 0, 0, 0, 58, 0, 0, 0, 77, 101, 109, 98, 101, 114, 0, 0, 20, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 3, 0, 1, 0, 132, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 3, 0, 1, 0, 140, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 3, 0, 1, 0, 160, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 3, 0, 1, 0, 168, 0, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 3, 0, 1, 0, 172, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 111, 99, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 101, 109, 98, 101, 114, 115, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 162, 31, 142, 137, 56, 144, 186, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f38e1de3041357ae = b_f38e1de3041357ae.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_f38e1de3041357ae[] = { &s_c2ba9038898e1fa2, }; static const uint16_t m_f38e1de3041357ae[] = {1, 4, 0, 2, 3}; static const uint16_t i_f38e1de3041357ae[] = {0, 1, 2, 3, 4}; const ::capnp::_::RawSchema s_f38e1de3041357ae = { 0xf38e1de3041357ae, b_f38e1de3041357ae.words, 102, d_f38e1de3041357ae, m_f38e1de3041357ae, 1, 5, i_f38e1de3041357ae, nullptr, nullptr, { &s_f38e1de3041357ae, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<35> b_c2ba9038898e1fa2 = { { 0, 0, 0, 0, 5, 0, 6, 0, 162, 31, 142, 137, 56, 144, 186, 194, 29, 0, 0, 0, 1, 0, 0, 0, 174, 87, 19, 4, 227, 29, 142, 243, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 34, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 46, 77, 101, 109, 98, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 24, 0, 0, 0, 2, 0, 1, 0, 100, 111, 99, 67, 111, 109, 109, 101, 110, 116, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c2ba9038898e1fa2 = b_c2ba9038898e1fa2.words; #if !CAPNP_LITE static const uint16_t m_c2ba9038898e1fa2[] = {0}; static const uint16_t i_c2ba9038898e1fa2[] = {0}; const ::capnp::_::RawSchema s_c2ba9038898e1fa2 = { 0xc2ba9038898e1fa2, b_c2ba9038898e1fa2.words, 35, nullptr, m_c2ba9038898e1fa2, 0, 1, i_c2ba9038898e1fa2, nullptr, nullptr, { &s_c2ba9038898e1fa2, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<134> b_9ea0b19b37fb4435 = { { 0, 0, 0, 0, 5, 0, 6, 0, 53, 68, 251, 55, 155, 177, 160, 158, 18, 0, 0, 0, 1, 0, 5, 0, 23, 164, 35, 249, 76, 171, 130, 230, 6, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 143, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 115, 116, 114, 117, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 3, 0, 1, 0, 192, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 0, 0, 0, 3, 0, 1, 0, 200, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 13, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 0, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 3, 0, 1, 0, 212, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 224, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 3, 0, 1, 0, 216, 0, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 3, 0, 1, 0, 228, 0, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 3, 0, 1, 0, 240, 0, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 3, 0, 1, 0, 4, 1, 0, 0, 2, 0, 1, 0, 100, 97, 116, 97, 87, 111, 114, 100, 67, 111, 117, 110, 116, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 111, 105, 110, 116, 101, 114, 67, 111, 117, 110, 116, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 114, 101, 102, 101, 114, 114, 101, 100, 76, 105, 115, 116, 69, 110, 99, 111, 100, 105, 110, 103, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 38, 25, 82, 186, 125, 143, 149, 209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 115, 71, 114, 111, 117, 112, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 99, 114, 105, 109, 105, 110, 97, 110, 116, 67, 111, 117, 110, 116, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 99, 114, 105, 109, 105, 110, 97, 110, 116, 79, 102, 102, 115, 101, 116, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 101, 108, 100, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 95, 244, 74, 31, 164, 80, 173, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9ea0b19b37fb4435 = b_9ea0b19b37fb4435.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9ea0b19b37fb4435[] = { &s_9aad50a41f4af45f, &s_d1958f7dba521926, &s_e682ab4cf923a417, }; static const uint16_t m_9ea0b19b37fb4435[] = {0, 4, 5, 6, 3, 1, 2}; static const uint16_t i_9ea0b19b37fb4435[] = {0, 1, 2, 3, 4, 5, 6}; const ::capnp::_::RawSchema s_9ea0b19b37fb4435 = { 0x9ea0b19b37fb4435, b_9ea0b19b37fb4435.words, 134, d_9ea0b19b37fb4435, m_9ea0b19b37fb4435, 3, 7, i_9ea0b19b37fb4435, nullptr, nullptr, { &s_9ea0b19b37fb4435, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<36> b_b54ab3364333f598 = { { 0, 0, 0, 0, 5, 0, 6, 0, 152, 245, 51, 67, 54, 179, 74, 181, 18, 0, 0, 0, 1, 0, 5, 0, 23, 164, 35, 249, 76, 171, 130, 230, 6, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 101, 110, 117, 109, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 40, 0, 0, 0, 2, 0, 1, 0, 101, 110, 117, 109, 101, 114, 97, 110, 116, 115, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 77, 154, 84, 220, 235, 124, 138, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b54ab3364333f598 = b_b54ab3364333f598.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_b54ab3364333f598[] = { &s_978a7cebdc549a4d, &s_e682ab4cf923a417, }; static const uint16_t m_b54ab3364333f598[] = {0}; static const uint16_t i_b54ab3364333f598[] = {0}; const ::capnp::_::RawSchema s_b54ab3364333f598 = { 0xb54ab3364333f598, b_b54ab3364333f598.words, 36, d_b54ab3364333f598, m_b54ab3364333f598, 2, 1, i_b54ab3364333f598, nullptr, nullptr, { &s_b54ab3364333f598, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<56> b_e82753cff0c2218f = { { 0, 0, 0, 0, 5, 0, 6, 0, 143, 33, 194, 240, 207, 83, 39, 232, 18, 0, 0, 0, 1, 0, 5, 0, 23, 164, 35, 249, 76, 171, 130, 230, 6, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 64, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 3, 0, 1, 0, 88, 0, 0, 0, 2, 0, 1, 0, 109, 101, 116, 104, 111, 100, 115, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 128, 77, 51, 59, 226, 204, 0, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 117, 112, 101, 114, 99, 108, 97, 115, 115, 101, 115, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 248, 215, 164, 208, 158, 42, 150, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_e82753cff0c2218f = b_e82753cff0c2218f.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_e82753cff0c2218f[] = { &s_9500cce23b334d80, &s_a9962a9ed0a4d7f8, &s_e682ab4cf923a417, }; static const uint16_t m_e82753cff0c2218f[] = {0, 1}; static const uint16_t i_e82753cff0c2218f[] = {0, 1}; const ::capnp::_::RawSchema s_e82753cff0c2218f = { 0xe82753cff0c2218f, b_e82753cff0c2218f.words, 56, d_e82753cff0c2218f, m_e82753cff0c2218f, 3, 2, i_e82753cff0c2218f, nullptr, nullptr, { &s_e82753cff0c2218f, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<46> b_b18aa5ac7a0d9420 = { { 0, 0, 0, 0, 5, 0, 6, 0, 32, 148, 13, 122, 172, 165, 138, 177, 18, 0, 0, 0, 1, 0, 5, 0, 23, 164, 35, 249, 76, 171, 130, 230, 6, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 99, 111, 110, 115, 116, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 96, 204, 249, 225, 237, 120, 115, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 155, 12, 176, 215, 210, 220, 35, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b18aa5ac7a0d9420 = b_b18aa5ac7a0d9420.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_b18aa5ac7a0d9420[] = { &s_ce23dcd2d7b00c9b, &s_d07378ede1f9cc60, &s_e682ab4cf923a417, }; static const uint16_t m_b18aa5ac7a0d9420[] = {0, 1}; static const uint16_t i_b18aa5ac7a0d9420[] = {0, 1}; const ::capnp::_::RawSchema s_b18aa5ac7a0d9420 = { 0xb18aa5ac7a0d9420, b_b18aa5ac7a0d9420.words, 46, d_b18aa5ac7a0d9420, m_b18aa5ac7a0d9420, 3, 2, i_b18aa5ac7a0d9420, nullptr, nullptr, { &s_b18aa5ac7a0d9420, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<227> b_ec1619d4400a0290 = { { 0, 0, 0, 0, 5, 0, 6, 0, 144, 2, 10, 64, 212, 25, 22, 236, 18, 0, 0, 0, 1, 0, 5, 0, 23, 164, 35, 249, 76, 171, 130, 230, 6, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 223, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 78, 111, 100, 101, 46, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 52, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 1, 0, 0, 3, 0, 1, 0, 100, 1, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 112, 0, 0, 0, 0, 0, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 1, 0, 0, 3, 0, 1, 0, 108, 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 113, 0, 0, 0, 0, 0, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 1, 0, 0, 3, 0, 1, 0, 116, 1, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 114, 0, 0, 0, 0, 0, 1, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 1, 0, 0, 3, 0, 1, 0, 124, 1, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 115, 0, 0, 0, 0, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 1, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 1, 0, 0, 3, 0, 1, 0, 136, 1, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 116, 0, 0, 0, 0, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 1, 0, 0, 3, 0, 1, 0, 144, 1, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 117, 0, 0, 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 1, 0, 0, 3, 0, 1, 0, 152, 1, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 118, 0, 0, 0, 0, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 1, 0, 0, 3, 0, 1, 0, 160, 1, 0, 0, 2, 0, 1, 0, 8, 0, 0, 0, 119, 0, 0, 0, 0, 0, 1, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 1, 0, 0, 3, 0, 1, 0, 168, 1, 0, 0, 2, 0, 1, 0, 9, 0, 0, 0, 120, 0, 0, 0, 0, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 1, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 1, 0, 0, 3, 0, 1, 0, 180, 1, 0, 0, 2, 0, 1, 0, 10, 0, 0, 0, 121, 0, 0, 0, 0, 0, 1, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 1, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 1, 0, 0, 3, 0, 1, 0, 188, 1, 0, 0, 2, 0, 1, 0, 11, 0, 0, 0, 122, 0, 0, 0, 0, 0, 1, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 1, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 1, 0, 0, 3, 0, 1, 0, 196, 1, 0, 0, 2, 0, 1, 0, 12, 0, 0, 0, 123, 0, 0, 0, 0, 0, 1, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 1, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 1, 0, 0, 3, 0, 1, 0, 208, 1, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 96, 204, 249, 225, 237, 120, 115, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 70, 105, 108, 101, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 67, 111, 110, 115, 116, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 69, 110, 117, 109, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 69, 110, 117, 109, 101, 114, 97, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 83, 116, 114, 117, 99, 116, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 70, 105, 101, 108, 100, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 85, 110, 105, 111, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 71, 114, 111, 117, 112, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 73, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 77, 101, 116, 104, 111, 100, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 80, 97, 114, 97, 109, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 97, 114, 103, 101, 116, 115, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ec1619d4400a0290 = b_ec1619d4400a0290.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_ec1619d4400a0290[] = { &s_d07378ede1f9cc60, &s_e682ab4cf923a417, }; static const uint16_t m_ec1619d4400a0290[] = {12, 2, 3, 4, 6, 1, 8, 9, 10, 11, 5, 7, 0}; static const uint16_t i_ec1619d4400a0290[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; const ::capnp::_::RawSchema s_ec1619d4400a0290 = { 0xec1619d4400a0290, b_ec1619d4400a0290.words, 227, d_ec1619d4400a0290, m_ec1619d4400a0290, 2, 13, i_ec1619d4400a0290, nullptr, nullptr, { &s_ec1619d4400a0290, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<113> b_9aad50a41f4af45f = { { 0, 0, 0, 0, 5, 0, 6, 0, 95, 244, 74, 31, 164, 80, 173, 154, 13, 0, 0, 0, 1, 0, 3, 0, 217, 114, 76, 98, 9, 197, 63, 169, 4, 0, 7, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 154, 0, 0, 0, 29, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 143, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 70, 105, 101, 108, 100, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 18, 199, 254, 124, 190, 76, 177, 151, 1, 0, 0, 0, 122, 0, 0, 0, 110, 111, 68, 105, 115, 99, 114, 105, 109, 105, 110, 97, 110, 116, 0, 0, 28, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 0, 0, 0, 3, 0, 1, 0, 188, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 3, 0, 1, 0, 196, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 3, 0, 1, 0, 220, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 3, 0, 1, 0, 232, 0, 0, 0, 2, 0, 1, 0, 4, 0, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 111, 116, 180, 107, 71, 5, 35, 196, 229, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 254, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 17, 29, 219, 104, 219, 205, 252, 202, 205, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 230, 11, 135, 135, 194, 213, 144, 187, 181, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 111, 100, 101, 79, 114, 100, 101, 114, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 66, 117, 37, 171, 13, 149, 200, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 105, 115, 99, 114, 105, 109, 105, 110, 97, 110, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 108, 111, 116, 0, 0, 0, 0, 103, 114, 111, 117, 112, 0, 0, 0, 111, 114, 100, 105, 110, 97, 108, 0, } }; ::capnp::word const* const bp_9aad50a41f4af45f = b_9aad50a41f4af45f.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9aad50a41f4af45f[] = { &s_bb90d5c287870be6, &s_c42305476bb4746f, &s_cafccddb68db1d11, &s_f1c8950dab257542, }; static const uint16_t m_9aad50a41f4af45f[] = {2, 1, 3, 5, 0, 6, 4}; static const uint16_t i_9aad50a41f4af45f[] = {4, 5, 0, 1, 2, 3, 6}; const ::capnp::_::RawSchema s_9aad50a41f4af45f = { 0x9aad50a41f4af45f, b_9aad50a41f4af45f.words, 113, d_9aad50a41f4af45f, m_9aad50a41f4af45f, 4, 7, i_9aad50a41f4af45f, nullptr, nullptr, { &s_9aad50a41f4af45f, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<25> b_97b14cbe7cfec712 = { { 0, 0, 0, 0, 5, 0, 6, 0, 18, 199, 254, 124, 190, 76, 177, 151, 19, 0, 0, 0, 4, 0, 0, 0, 95, 244, 74, 31, 164, 80, 173, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 1, 0, 44, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 70, 105, 101, 108, 100, 46, 110, 111, 68, 105, 115, 99, 114, 105, 109, 105, 110, 97, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_97b14cbe7cfec712 = b_97b14cbe7cfec712.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_97b14cbe7cfec712 = { 0x97b14cbe7cfec712, b_97b14cbe7cfec712.words, 25, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_97b14cbe7cfec712, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<79> b_c42305476bb4746f = { { 0, 0, 0, 0, 5, 0, 6, 0, 111, 116, 180, 107, 71, 5, 35, 196, 19, 0, 0, 0, 1, 0, 3, 0, 95, 244, 74, 31, 164, 80, 173, 154, 4, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 70, 105, 101, 108, 100, 46, 115, 108, 111, 116, 0, 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 3, 0, 1, 0, 104, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 3, 0, 1, 0, 108, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 3, 0, 1, 0, 116, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 128, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 3, 0, 1, 0, 128, 0, 0, 0, 2, 0, 1, 0, 111, 102, 102, 115, 101, 116, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 96, 204, 249, 225, 237, 120, 115, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 155, 12, 176, 215, 210, 220, 35, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 97, 100, 69, 120, 112, 108, 105, 99, 105, 116, 68, 101, 102, 97, 117, 108, 116, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c42305476bb4746f = b_c42305476bb4746f.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c42305476bb4746f[] = { &s_9aad50a41f4af45f, &s_ce23dcd2d7b00c9b, &s_d07378ede1f9cc60, }; static const uint16_t m_c42305476bb4746f[] = {2, 3, 0, 1}; static const uint16_t i_c42305476bb4746f[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_c42305476bb4746f = { 0xc42305476bb4746f, b_c42305476bb4746f.words, 79, d_c42305476bb4746f, m_c42305476bb4746f, 3, 4, i_c42305476bb4746f, nullptr, nullptr, { &s_c42305476bb4746f, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<32> b_cafccddb68db1d11 = { { 0, 0, 0, 0, 5, 0, 6, 0, 17, 29, 219, 104, 219, 205, 252, 202, 19, 0, 0, 0, 1, 0, 3, 0, 95, 244, 74, 31, 164, 80, 173, 154, 4, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 70, 105, 101, 108, 100, 46, 103, 114, 111, 117, 112, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 73, 100, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_cafccddb68db1d11 = b_cafccddb68db1d11.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_cafccddb68db1d11[] = { &s_9aad50a41f4af45f, }; static const uint16_t m_cafccddb68db1d11[] = {0}; static const uint16_t i_cafccddb68db1d11[] = {0}; const ::capnp::_::RawSchema s_cafccddb68db1d11 = { 0xcafccddb68db1d11, b_cafccddb68db1d11.words, 32, d_cafccddb68db1d11, m_cafccddb68db1d11, 1, 1, i_cafccddb68db1d11, nullptr, nullptr, { &s_cafccddb68db1d11, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_bb90d5c287870be6 = { { 0, 0, 0, 0, 5, 0, 6, 0, 230, 11, 135, 135, 194, 213, 144, 187, 19, 0, 0, 0, 1, 0, 3, 0, 95, 244, 74, 31, 164, 80, 173, 154, 4, 0, 7, 0, 1, 0, 2, 0, 5, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 70, 105, 101, 108, 100, 46, 111, 114, 100, 105, 110, 97, 108, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 6, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 3, 0, 1, 0, 60, 0, 0, 0, 2, 0, 1, 0, 105, 109, 112, 108, 105, 99, 105, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 120, 112, 108, 105, 99, 105, 116, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_bb90d5c287870be6 = b_bb90d5c287870be6.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_bb90d5c287870be6[] = { &s_9aad50a41f4af45f, }; static const uint16_t m_bb90d5c287870be6[] = {1, 0}; static const uint16_t i_bb90d5c287870be6[] = {0, 1}; const ::capnp::_::RawSchema s_bb90d5c287870be6 = { 0xbb90d5c287870be6, b_bb90d5c287870be6.words, 49, d_bb90d5c287870be6, m_bb90d5c287870be6, 1, 2, i_bb90d5c287870be6, nullptr, nullptr, { &s_bb90d5c287870be6, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<68> b_978a7cebdc549a4d = { { 0, 0, 0, 0, 5, 0, 6, 0, 77, 154, 84, 220, 235, 124, 138, 151, 13, 0, 0, 0, 1, 0, 1, 0, 217, 114, 76, 98, 9, 197, 63, 169, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 69, 110, 117, 109, 101, 114, 97, 110, 116, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 3, 0, 1, 0, 108, 0, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 111, 100, 101, 79, 114, 100, 101, 114, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 66, 117, 37, 171, 13, 149, 200, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_978a7cebdc549a4d = b_978a7cebdc549a4d.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_978a7cebdc549a4d[] = { &s_f1c8950dab257542, }; static const uint16_t m_978a7cebdc549a4d[] = {2, 1, 0}; static const uint16_t i_978a7cebdc549a4d[] = {0, 1, 2}; const ::capnp::_::RawSchema s_978a7cebdc549a4d = { 0x978a7cebdc549a4d, b_978a7cebdc549a4d.words, 68, d_978a7cebdc549a4d, m_978a7cebdc549a4d, 1, 3, i_978a7cebdc549a4d, nullptr, nullptr, { &s_978a7cebdc549a4d, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<47> b_a9962a9ed0a4d7f8 = { { 0, 0, 0, 0, 5, 0, 6, 0, 248, 215, 164, 208, 158, 42, 150, 169, 13, 0, 0, 0, 1, 0, 1, 0, 217, 114, 76, 98, 9, 197, 63, 169, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 83, 117, 112, 101, 114, 99, 108, 97, 115, 115, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 110, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_a9962a9ed0a4d7f8 = b_a9962a9ed0a4d7f8.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_a9962a9ed0a4d7f8[] = { &s_903455f06065422b, }; static const uint16_t m_a9962a9ed0a4d7f8[] = {1, 0}; static const uint16_t i_a9962a9ed0a4d7f8[] = {0, 1}; const ::capnp::_::RawSchema s_a9962a9ed0a4d7f8 = { 0xa9962a9ed0a4d7f8, b_a9962a9ed0a4d7f8.words, 47, d_a9962a9ed0a4d7f8, m_a9962a9ed0a4d7f8, 1, 2, i_a9962a9ed0a4d7f8, nullptr, nullptr, { &s_a9962a9ed0a4d7f8, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<154> b_9500cce23b334d80 = { { 0, 0, 0, 0, 5, 0, 6, 0, 128, 77, 51, 59, 226, 204, 0, 149, 13, 0, 0, 0, 1, 0, 3, 0, 217, 114, 76, 98, 9, 197, 63, 169, 5, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 162, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 199, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 77, 101, 116, 104, 111, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 32, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 3, 0, 1, 0, 216, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 3, 0, 1, 0, 224, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 3, 0, 1, 0, 232, 0, 0, 0, 2, 0, 1, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 3, 0, 1, 0, 244, 0, 0, 0, 2, 0, 1, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 3, 0, 1, 0, 12, 1, 0, 0, 2, 0, 1, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 3, 0, 1, 0, 20, 1, 0, 0, 2, 0, 1, 0, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 1, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, 0, 3, 0, 1, 0, 28, 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 0, 0, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 1, 0, 0, 3, 0, 1, 0, 56, 1, 0, 0, 2, 0, 1, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 111, 100, 101, 79, 114, 100, 101, 114, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 83, 116, 114, 117, 99, 116, 84, 121, 112, 101, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 117, 108, 116, 83, 116, 114, 117, 99, 116, 84, 121, 112, 101, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 66, 117, 37, 171, 13, 149, 200, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 66, 114, 97, 110, 100, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 115, 117, 108, 116, 66, 114, 97, 110, 100, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 109, 112, 108, 105, 99, 105, 116, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 177, 163, 15, 241, 204, 27, 82, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9500cce23b334d80 = b_9500cce23b334d80.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9500cce23b334d80[] = { &s_903455f06065422b, &s_b9521bccf10fa3b1, &s_f1c8950dab257542, }; static const uint16_t m_9500cce23b334d80[] = {4, 1, 7, 0, 5, 2, 6, 3}; static const uint16_t i_9500cce23b334d80[] = {0, 1, 2, 3, 4, 5, 6, 7}; const ::capnp::_::RawSchema s_9500cce23b334d80 = { 0x9500cce23b334d80, b_9500cce23b334d80.words, 154, d_9500cce23b334d80, m_9500cce23b334d80, 3, 8, i_9500cce23b334d80, nullptr, nullptr, { &s_9500cce23b334d80, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<269> b_d07378ede1f9cc60 = { { 0, 0, 0, 0, 5, 0, 6, 0, 96, 204, 249, 225, 237, 120, 115, 208, 13, 0, 0, 0, 1, 0, 3, 0, 217, 114, 76, 98, 9, 197, 63, 169, 1, 0, 7, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 146, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 47, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 76, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 1, 0, 12, 2, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 3, 0, 1, 0, 16, 2, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 3, 0, 1, 0, 20, 2, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 3, 0, 1, 0, 24, 2, 0, 0, 2, 0, 1, 0, 4, 0, 251, 255, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2, 0, 0, 3, 0, 1, 0, 28, 2, 0, 0, 2, 0, 1, 0, 5, 0, 250, 255, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 0, 0, 3, 0, 1, 0, 32, 2, 0, 0, 2, 0, 1, 0, 6, 0, 249, 255, 0, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 0, 3, 0, 1, 0, 36, 2, 0, 0, 2, 0, 1, 0, 7, 0, 248, 255, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 0, 0, 3, 0, 1, 0, 40, 2, 0, 0, 2, 0, 1, 0, 8, 0, 247, 255, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 2, 0, 0, 3, 0, 1, 0, 44, 2, 0, 0, 2, 0, 1, 0, 9, 0, 246, 255, 0, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 2, 0, 0, 3, 0, 1, 0, 48, 2, 0, 0, 2, 0, 1, 0, 10, 0, 245, 255, 0, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 2, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 2, 0, 0, 3, 0, 1, 0, 52, 2, 0, 0, 2, 0, 1, 0, 11, 0, 244, 255, 0, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 2, 0, 0, 3, 0, 1, 0, 56, 2, 0, 0, 2, 0, 1, 0, 12, 0, 243, 255, 0, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 2, 0, 0, 3, 0, 1, 0, 60, 2, 0, 0, 2, 0, 1, 0, 13, 0, 242, 255, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 2, 0, 0, 3, 0, 1, 0, 64, 2, 0, 0, 2, 0, 1, 0, 14, 0, 241, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 151, 234, 96, 10, 37, 57, 231, 135, 61, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 240, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 169, 135, 127, 26, 113, 120, 14, 158, 37, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 239, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 211, 198, 76, 239, 96, 111, 58, 172, 13, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 238, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 191, 12, 251, 247, 105, 202, 139, 237, 245, 1, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 237, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 241, 73, 62, 162, 232, 63, 87, 194, 225, 1, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 111, 105, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 111, 111, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 49, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 49, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 51, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 54, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 101, 120, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 97, 116, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 105, 115, 116, 0, 0, 0, 0, 101, 110, 117, 109, 0, 0, 0, 0, 115, 116, 114, 117, 99, 116, 0, 0, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d07378ede1f9cc60 = b_d07378ede1f9cc60.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_d07378ede1f9cc60[] = { &s_87e739250a60ea97, &s_9e0e78711a7f87a9, &s_ac3a6f60ef4cc6d3, &s_c2573fe8a23e49f1, &s_ed8bca69f7fb0cbf, }; static const uint16_t m_d07378ede1f9cc60[] = {18, 1, 13, 15, 10, 11, 3, 4, 5, 2, 17, 14, 16, 12, 7, 8, 9, 6, 0}; static const uint16_t i_d07378ede1f9cc60[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; const ::capnp::_::RawSchema s_d07378ede1f9cc60 = { 0xd07378ede1f9cc60, b_d07378ede1f9cc60.words, 269, d_d07378ede1f9cc60, m_d07378ede1f9cc60, 5, 19, i_d07378ede1f9cc60, nullptr, nullptr, { &s_d07378ede1f9cc60, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<32> b_87e739250a60ea97 = { { 0, 0, 0, 0, 5, 0, 6, 0, 151, 234, 96, 10, 37, 57, 231, 135, 18, 0, 0, 0, 1, 0, 3, 0, 96, 204, 249, 225, 237, 120, 115, 208, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 108, 105, 115, 116, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 24, 0, 0, 0, 2, 0, 1, 0, 101, 108, 101, 109, 101, 110, 116, 84, 121, 112, 101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 96, 204, 249, 225, 237, 120, 115, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_87e739250a60ea97 = b_87e739250a60ea97.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_87e739250a60ea97[] = { &s_d07378ede1f9cc60, }; static const uint16_t m_87e739250a60ea97[] = {0}; static const uint16_t i_87e739250a60ea97[] = {0}; const ::capnp::_::RawSchema s_87e739250a60ea97 = { 0x87e739250a60ea97, b_87e739250a60ea97.words, 32, d_87e739250a60ea97, m_87e739250a60ea97, 1, 1, i_87e739250a60ea97, nullptr, nullptr, { &s_87e739250a60ea97, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<46> b_9e0e78711a7f87a9 = { { 0, 0, 0, 0, 5, 0, 6, 0, 169, 135, 127, 26, 113, 120, 14, 158, 18, 0, 0, 0, 1, 0, 3, 0, 96, 204, 249, 225, 237, 120, 115, 208, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 101, 110, 117, 109, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 73, 100, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 110, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9e0e78711a7f87a9 = b_9e0e78711a7f87a9.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9e0e78711a7f87a9[] = { &s_903455f06065422b, &s_d07378ede1f9cc60, }; static const uint16_t m_9e0e78711a7f87a9[] = {1, 0}; static const uint16_t i_9e0e78711a7f87a9[] = {0, 1}; const ::capnp::_::RawSchema s_9e0e78711a7f87a9 = { 0x9e0e78711a7f87a9, b_9e0e78711a7f87a9.words, 46, d_9e0e78711a7f87a9, m_9e0e78711a7f87a9, 2, 2, i_9e0e78711a7f87a9, nullptr, nullptr, { &s_9e0e78711a7f87a9, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<47> b_ac3a6f60ef4cc6d3 = { { 0, 0, 0, 0, 5, 0, 6, 0, 211, 198, 76, 239, 96, 111, 58, 172, 18, 0, 0, 0, 1, 0, 3, 0, 96, 204, 249, 225, 237, 120, 115, 208, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 115, 116, 114, 117, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 73, 100, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 110, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ac3a6f60ef4cc6d3 = b_ac3a6f60ef4cc6d3.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_ac3a6f60ef4cc6d3[] = { &s_903455f06065422b, &s_d07378ede1f9cc60, }; static const uint16_t m_ac3a6f60ef4cc6d3[] = {1, 0}; static const uint16_t i_ac3a6f60ef4cc6d3[] = {0, 1}; const ::capnp::_::RawSchema s_ac3a6f60ef4cc6d3 = { 0xac3a6f60ef4cc6d3, b_ac3a6f60ef4cc6d3.words, 47, d_ac3a6f60ef4cc6d3, m_ac3a6f60ef4cc6d3, 2, 2, i_ac3a6f60ef4cc6d3, nullptr, nullptr, { &s_ac3a6f60ef4cc6d3, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<47> b_ed8bca69f7fb0cbf = { { 0, 0, 0, 0, 5, 0, 6, 0, 191, 12, 251, 247, 105, 202, 139, 237, 18, 0, 0, 0, 1, 0, 3, 0, 96, 204, 249, 225, 237, 120, 115, 208, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 116, 121, 112, 101, 73, 100, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 110, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ed8bca69f7fb0cbf = b_ed8bca69f7fb0cbf.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_ed8bca69f7fb0cbf[] = { &s_903455f06065422b, &s_d07378ede1f9cc60, }; static const uint16_t m_ed8bca69f7fb0cbf[] = {1, 0}; static const uint16_t i_ed8bca69f7fb0cbf[] = {0, 1}; const ::capnp::_::RawSchema s_ed8bca69f7fb0cbf = { 0xed8bca69f7fb0cbf, b_ed8bca69f7fb0cbf.words, 47, d_ed8bca69f7fb0cbf, m_ed8bca69f7fb0cbf, 2, 2, i_ed8bca69f7fb0cbf, nullptr, nullptr, { &s_ed8bca69f7fb0cbf, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<45> b_c2573fe8a23e49f1 = { { 0, 0, 0, 0, 5, 0, 6, 0, 241, 73, 62, 162, 232, 63, 87, 194, 18, 0, 0, 0, 1, 0, 3, 0, 96, 204, 249, 225, 237, 120, 115, 208, 1, 0, 7, 0, 1, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 86, 54, 89, 254, 121, 95, 59, 142, 69, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 254, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 133, 74, 97, 244, 36, 247, 209, 157, 49, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 253, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 116, 226, 86, 12, 18, 201, 239, 186, 29, 0, 0, 0, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 110, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 0, 0, 0, 112, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 0, 0, 0, 0, 0, 105, 109, 112, 108, 105, 99, 105, 116, 77, 101, 116, 104, 111, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, } }; ::capnp::word const* const bp_c2573fe8a23e49f1 = b_c2573fe8a23e49f1.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c2573fe8a23e49f1[] = { &s_8e3b5f79fe593656, &s_9dd1f724f4614a85, &s_baefc9120c56e274, &s_d07378ede1f9cc60, }; static const uint16_t m_c2573fe8a23e49f1[] = {2, 1, 0}; static const uint16_t i_c2573fe8a23e49f1[] = {0, 1, 2}; const ::capnp::_::RawSchema s_c2573fe8a23e49f1 = { 0xc2573fe8a23e49f1, b_c2573fe8a23e49f1.words, 45, d_c2573fe8a23e49f1, m_c2573fe8a23e49f1, 4, 3, i_c2573fe8a23e49f1, nullptr, nullptr, { &s_c2573fe8a23e49f1, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<80> b_8e3b5f79fe593656 = { { 0, 0, 0, 0, 5, 0, 6, 0, 86, 54, 89, 254, 121, 95, 59, 142, 29, 0, 0, 0, 1, 0, 3, 0, 241, 73, 62, 162, 232, 63, 87, 194, 1, 0, 7, 0, 1, 0, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 90, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 46, 117, 110, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 3, 0, 1, 0, 104, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 3, 0, 1, 0, 108, 0, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 0, 0, 0, 0, 0, 0, 1, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 3, 0, 1, 0, 112, 0, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 0, 0, 0, 0, 0, 0, 1, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 3, 0, 1, 0, 120, 0, 0, 0, 2, 0, 1, 0, 97, 110, 121, 75, 105, 110, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 117, 99, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 105, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 97, 98, 105, 108, 105, 116, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_8e3b5f79fe593656 = b_8e3b5f79fe593656.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_8e3b5f79fe593656[] = { &s_c2573fe8a23e49f1, }; static const uint16_t m_8e3b5f79fe593656[] = {0, 3, 2, 1}; static const uint16_t i_8e3b5f79fe593656[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_8e3b5f79fe593656 = { 0x8e3b5f79fe593656, b_8e3b5f79fe593656.words, 80, d_8e3b5f79fe593656, m_8e3b5f79fe593656, 1, 4, i_8e3b5f79fe593656, nullptr, nullptr, { &s_8e3b5f79fe593656, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<49> b_9dd1f724f4614a85 = { { 0, 0, 0, 0, 5, 0, 6, 0, 133, 74, 97, 244, 36, 247, 209, 157, 29, 0, 0, 0, 1, 0, 3, 0, 241, 73, 62, 162, 232, 63, 87, 194, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 46, 112, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 115, 99, 111, 112, 101, 73, 100, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 97, 114, 97, 109, 101, 116, 101, 114, 73, 110, 100, 101, 120, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_9dd1f724f4614a85 = b_9dd1f724f4614a85.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_9dd1f724f4614a85[] = { &s_c2573fe8a23e49f1, }; static const uint16_t m_9dd1f724f4614a85[] = {1, 0}; static const uint16_t i_9dd1f724f4614a85[] = {0, 1}; const ::capnp::_::RawSchema s_9dd1f724f4614a85 = { 0x9dd1f724f4614a85, b_9dd1f724f4614a85.words, 49, d_9dd1f724f4614a85, m_9dd1f724f4614a85, 1, 2, i_9dd1f724f4614a85, nullptr, nullptr, { &s_9dd1f724f4614a85, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<36> b_baefc9120c56e274 = { { 0, 0, 0, 0, 5, 0, 6, 0, 116, 226, 86, 12, 18, 201, 239, 186, 29, 0, 0, 0, 1, 0, 3, 0, 241, 73, 62, 162, 232, 63, 87, 194, 1, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 170, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 84, 121, 112, 101, 46, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 46, 105, 109, 112, 108, 105, 99, 105, 116, 77, 101, 116, 104, 111, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 24, 0, 0, 0, 2, 0, 1, 0, 112, 97, 114, 97, 109, 101, 116, 101, 114, 73, 110, 100, 101, 120, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_baefc9120c56e274 = b_baefc9120c56e274.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_baefc9120c56e274[] = { &s_c2573fe8a23e49f1, }; static const uint16_t m_baefc9120c56e274[] = {0}; static const uint16_t i_baefc9120c56e274[] = {0}; const ::capnp::_::RawSchema s_baefc9120c56e274 = { 0xbaefc9120c56e274, b_baefc9120c56e274.words, 36, d_baefc9120c56e274, m_baefc9120c56e274, 1, 1, i_baefc9120c56e274, nullptr, nullptr, { &s_baefc9120c56e274, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<42> b_903455f06065422b = { { 0, 0, 0, 0, 5, 0, 6, 0, 43, 66, 101, 96, 240, 85, 52, 144, 13, 0, 0, 0, 1, 0, 0, 0, 217, 114, 76, 98, 9, 197, 63, 169, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 154, 0, 0, 0, 29, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 66, 114, 97, 110, 100, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 201, 107, 99, 169, 133, 52, 215, 171, 9, 0, 0, 0, 50, 0, 0, 0, 252, 231, 158, 150, 22, 205, 99, 200, 5, 0, 0, 0, 66, 0, 0, 0, 83, 99, 111, 112, 101, 0, 0, 0, 66, 105, 110, 100, 105, 110, 103, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 36, 0, 0, 0, 2, 0, 1, 0, 115, 99, 111, 112, 101, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 201, 107, 99, 169, 133, 52, 215, 171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_903455f06065422b = b_903455f06065422b.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_903455f06065422b[] = { &s_abd73485a9636bc9, }; static const uint16_t m_903455f06065422b[] = {0}; static const uint16_t i_903455f06065422b[] = {0}; const ::capnp::_::RawSchema s_903455f06065422b = { 0x903455f06065422b, b_903455f06065422b.words, 42, d_903455f06065422b, m_903455f06065422b, 1, 1, i_903455f06065422b, nullptr, nullptr, { &s_903455f06065422b, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<67> b_abd73485a9636bc9 = { { 0, 0, 0, 0, 5, 0, 6, 0, 201, 107, 99, 169, 133, 52, 215, 171, 19, 0, 0, 0, 1, 0, 2, 0, 43, 66, 101, 96, 240, 85, 52, 144, 1, 0, 7, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 202, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 66, 114, 97, 110, 100, 46, 83, 99, 111, 112, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 96, 0, 0, 0, 2, 0, 1, 0, 2, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 3, 0, 1, 0, 100, 0, 0, 0, 2, 0, 1, 0, 115, 99, 111, 112, 101, 73, 100, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 105, 110, 100, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 252, 231, 158, 150, 22, 205, 99, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 104, 101, 114, 105, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_abd73485a9636bc9 = b_abd73485a9636bc9.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_abd73485a9636bc9[] = { &s_c863cd16969ee7fc, }; static const uint16_t m_abd73485a9636bc9[] = {1, 2, 0}; static const uint16_t i_abd73485a9636bc9[] = {1, 2, 0}; const ::capnp::_::RawSchema s_abd73485a9636bc9 = { 0xabd73485a9636bc9, b_abd73485a9636bc9.words, 67, d_abd73485a9636bc9, m_abd73485a9636bc9, 1, 3, i_abd73485a9636bc9, nullptr, nullptr, { &s_abd73485a9636bc9, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<48> b_c863cd16969ee7fc = { { 0, 0, 0, 0, 5, 0, 6, 0, 252, 231, 158, 150, 22, 205, 99, 200, 19, 0, 0, 0, 1, 0, 1, 0, 43, 66, 101, 96, 240, 85, 52, 144, 1, 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 218, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 66, 114, 97, 110, 100, 46, 66, 105, 110, 100, 105, 110, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 117, 110, 98, 111, 117, 110, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 96, 204, 249, 225, 237, 120, 115, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_c863cd16969ee7fc = b_c863cd16969ee7fc.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c863cd16969ee7fc[] = { &s_d07378ede1f9cc60, }; static const uint16_t m_c863cd16969ee7fc[] = {1, 0}; static const uint16_t i_c863cd16969ee7fc[] = {0, 1}; const ::capnp::_::RawSchema s_c863cd16969ee7fc = { 0xc863cd16969ee7fc, b_c863cd16969ee7fc.words, 48, d_c863cd16969ee7fc, m_c863cd16969ee7fc, 1, 2, i_c863cd16969ee7fc, nullptr, nullptr, { &s_c863cd16969ee7fc, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<304> b_ce23dcd2d7b00c9b = { { 0, 0, 0, 0, 5, 0, 6, 0, 155, 12, 176, 215, 210, 220, 35, 206, 13, 0, 0, 0, 1, 0, 2, 0, 217, 114, 76, 98, 9, 197, 63, 169, 1, 0, 7, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 154, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 47, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 86, 97, 108, 117, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 76, 0, 0, 0, 3, 0, 4, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 1, 0, 12, 2, 0, 0, 2, 0, 1, 0, 1, 0, 254, 255, 16, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 3, 0, 1, 0, 16, 2, 0, 0, 2, 0, 1, 0, 2, 0, 253, 255, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 3, 0, 1, 0, 20, 2, 0, 0, 2, 0, 1, 0, 3, 0, 252, 255, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 3, 0, 1, 0, 24, 2, 0, 0, 2, 0, 1, 0, 4, 0, 251, 255, 1, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2, 0, 0, 3, 0, 1, 0, 28, 2, 0, 0, 2, 0, 1, 0, 5, 0, 250, 255, 1, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 0, 0, 3, 0, 1, 0, 32, 2, 0, 0, 2, 0, 1, 0, 6, 0, 249, 255, 2, 0, 0, 0, 0, 0, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 2, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 0, 3, 0, 1, 0, 36, 2, 0, 0, 2, 0, 1, 0, 7, 0, 248, 255, 1, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 0, 0, 3, 0, 1, 0, 40, 2, 0, 0, 2, 0, 1, 0, 8, 0, 247, 255, 1, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 2, 0, 0, 3, 0, 1, 0, 44, 2, 0, 0, 2, 0, 1, 0, 9, 0, 246, 255, 1, 0, 0, 0, 0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 2, 0, 0, 3, 0, 1, 0, 48, 2, 0, 0, 2, 0, 1, 0, 10, 0, 245, 255, 1, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 2, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 2, 0, 0, 3, 0, 1, 0, 52, 2, 0, 0, 2, 0, 1, 0, 11, 0, 244, 255, 1, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 2, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 2, 0, 0, 3, 0, 1, 0, 56, 2, 0, 0, 2, 0, 1, 0, 12, 0, 243, 255, 0, 0, 0, 0, 0, 0, 1, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 2, 0, 0, 3, 0, 1, 0, 60, 2, 0, 0, 2, 0, 1, 0, 13, 0, 242, 255, 0, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 2, 0, 0, 3, 0, 1, 0, 64, 2, 0, 0, 2, 0, 1, 0, 14, 0, 241, 255, 0, 0, 0, 0, 0, 0, 1, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 2, 0, 0, 3, 0, 1, 0, 68, 2, 0, 0, 2, 0, 1, 0, 15, 0, 240, 255, 1, 0, 0, 0, 0, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 2, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 2, 0, 0, 3, 0, 1, 0, 72, 2, 0, 0, 2, 0, 1, 0, 16, 0, 239, 255, 0, 0, 0, 0, 0, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 2, 0, 0, 3, 0, 1, 0, 76, 2, 0, 0, 2, 0, 1, 0, 17, 0, 238, 255, 0, 0, 0, 0, 0, 0, 1, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 2, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 2, 0, 0, 3, 0, 1, 0, 84, 2, 0, 0, 2, 0, 1, 0, 18, 0, 237, 255, 0, 0, 0, 0, 0, 0, 1, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 2, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 2, 0, 0, 3, 0, 1, 0, 92, 2, 0, 0, 2, 0, 1, 0, 118, 111, 105, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 111, 111, 108, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 56, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 49, 54, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 51, 50, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 54, 52, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 56, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 49, 54, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 51, 50, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 105, 110, 116, 54, 52, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 51, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 108, 111, 97, 116, 54, 52, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 101, 120, 116, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 97, 116, 97, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 105, 115, 116, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 117, 109, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 114, 117, 99, 116, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 110, 116, 101, 114, 102, 97, 99, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 110, 121, 80, 111, 105, 110, 116, 101, 114, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ce23dcd2d7b00c9b = b_ce23dcd2d7b00c9b.words; #if !CAPNP_LITE static const uint16_t m_ce23dcd2d7b00c9b[] = {18, 1, 13, 15, 10, 11, 3, 4, 5, 2, 17, 14, 16, 12, 7, 8, 9, 6, 0}; static const uint16_t i_ce23dcd2d7b00c9b[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; const ::capnp::_::RawSchema s_ce23dcd2d7b00c9b = { 0xce23dcd2d7b00c9b, b_ce23dcd2d7b00c9b.words, 304, nullptr, m_ce23dcd2d7b00c9b, 0, 19, i_ce23dcd2d7b00c9b, nullptr, nullptr, { &s_ce23dcd2d7b00c9b, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<62> b_f1c8950dab257542 = { { 0, 0, 0, 0, 5, 0, 6, 0, 66, 117, 37, 171, 13, 149, 200, 241, 13, 0, 0, 0, 1, 0, 1, 0, 217, 114, 76, 98, 9, 197, 63, 169, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 194, 0, 0, 0, 29, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 108, 117, 101, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 155, 12, 176, 215, 210, 220, 35, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 114, 97, 110, 100, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 43, 66, 101, 96, 240, 85, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f1c8950dab257542 = b_f1c8950dab257542.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_f1c8950dab257542[] = { &s_903455f06065422b, &s_ce23dcd2d7b00c9b, }; static const uint16_t m_f1c8950dab257542[] = {2, 0, 1}; static const uint16_t i_f1c8950dab257542[] = {0, 1, 2}; const ::capnp::_::RawSchema s_f1c8950dab257542 = { 0xf1c8950dab257542, b_f1c8950dab257542.words, 62, d_f1c8950dab257542, m_f1c8950dab257542, 2, 3, i_f1c8950dab257542, nullptr, nullptr, { &s_f1c8950dab257542, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<54> b_d1958f7dba521926 = { { 0, 0, 0, 0, 5, 0, 6, 0, 38, 25, 82, 186, 125, 143, 149, 209, 13, 0, 0, 0, 2, 0, 0, 0, 217, 114, 76, 98, 9, 197, 63, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 202, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 69, 108, 101, 109, 101, 110, 116, 83, 105, 122, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 32, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 109, 112, 116, 121, 0, 0, 0, 98, 105, 116, 0, 0, 0, 0, 0, 98, 121, 116, 101, 0, 0, 0, 0, 116, 119, 111, 66, 121, 116, 101, 115, 0, 0, 0, 0, 0, 0, 0, 0, 102, 111, 117, 114, 66, 121, 116, 101, 115, 0, 0, 0, 0, 0, 0, 0, 101, 105, 103, 104, 116, 66, 121, 116, 101, 115, 0, 0, 0, 0, 0, 0, 112, 111, 105, 110, 116, 101, 114, 0, 105, 110, 108, 105, 110, 101, 67, 111, 109, 112, 111, 115, 105, 116, 101, 0, } }; ::capnp::word const* const bp_d1958f7dba521926 = b_d1958f7dba521926.words; #if !CAPNP_LITE static const uint16_t m_d1958f7dba521926[] = {1, 2, 5, 0, 4, 7, 6, 3}; const ::capnp::_::RawSchema s_d1958f7dba521926 = { 0xd1958f7dba521926, b_d1958f7dba521926.words, 54, nullptr, m_d1958f7dba521926, 0, 8, nullptr, nullptr, nullptr, { &s_d1958f7dba521926, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE CAPNP_DEFINE_ENUM(ElementSize_d1958f7dba521926, d1958f7dba521926); static const ::capnp::_::AlignedData<63> b_d85d305b7d839963 = { { 0, 0, 0, 0, 5, 0, 6, 0, 99, 153, 131, 125, 91, 48, 93, 216, 13, 0, 0, 0, 1, 0, 1, 0, 217, 114, 76, 98, 9, 197, 63, 169, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 210, 0, 0, 0, 33, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 97, 112, 110, 112, 86, 101, 114, 115, 105, 111, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 12, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 3, 0, 1, 0, 76, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 3, 0, 1, 0, 80, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 3, 0, 1, 0, 84, 0, 0, 0, 2, 0, 1, 0, 109, 97, 106, 111, 114, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 105, 110, 111, 114, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 105, 99, 114, 111, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_d85d305b7d839963 = b_d85d305b7d839963.words; #if !CAPNP_LITE static const uint16_t m_d85d305b7d839963[] = {0, 2, 1}; static const uint16_t i_d85d305b7d839963[] = {0, 1, 2}; const ::capnp::_::RawSchema s_d85d305b7d839963 = { 0xd85d305b7d839963, b_d85d305b7d839963.words, 63, nullptr, m_d85d305b7d839963, 0, 3, i_d85d305b7d839963, nullptr, nullptr, { &s_d85d305b7d839963, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<98> b_bfc546f6210ad7ce = { { 0, 0, 0, 0, 5, 0, 6, 0, 206, 215, 10, 33, 246, 70, 197, 191, 13, 0, 0, 0, 1, 0, 0, 0, 217, 114, 76, 98, 9, 197, 63, 169, 4, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 98, 0, 129, 46, 176, 14, 234, 207, 1, 0, 0, 0, 114, 0, 0, 0, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 0, 0, 0, 16, 0, 0, 0, 3, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 3, 0, 1, 0, 120, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 3, 0, 1, 0, 144, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 3, 0, 1, 0, 152, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 3, 0, 1, 0, 176, 0, 0, 0, 2, 0, 1, 0, 110, 111, 100, 101, 115, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 23, 164, 35, 249, 76, 171, 130, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 115, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 98, 0, 129, 46, 176, 14, 234, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 86, 101, 114, 115, 105, 111, 110, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 99, 153, 131, 125, 91, 48, 93, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 174, 87, 19, 4, 227, 29, 142, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_bfc546f6210ad7ce = b_bfc546f6210ad7ce.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_bfc546f6210ad7ce[] = { &s_cfea0eb02e810062, &s_d85d305b7d839963, &s_e682ab4cf923a417, &s_f38e1de3041357ae, }; static const uint16_t m_bfc546f6210ad7ce[] = {2, 0, 1, 3}; static const uint16_t i_bfc546f6210ad7ce[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_bfc546f6210ad7ce = { 0xbfc546f6210ad7ce, b_bfc546f6210ad7ce.words, 98, d_bfc546f6210ad7ce, m_bfc546f6210ad7ce, 4, 4, i_bfc546f6210ad7ce, nullptr, nullptr, { &s_bfc546f6210ad7ce, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<93> b_cfea0eb02e810062 = { { 0, 0, 0, 0, 5, 0, 6, 0, 98, 0, 129, 46, 176, 14, 234, 207, 34, 0, 0, 0, 1, 0, 1, 0, 206, 215, 10, 33, 246, 70, 197, 191, 3, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 130, 1, 0, 0, 41, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 46, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 0, 8, 0, 0, 0, 1, 0, 1, 0, 229, 87, 35, 18, 147, 65, 80, 174, 9, 0, 0, 0, 58, 0, 0, 0, 160, 93, 146, 118, 241, 43, 234, 248, 5, 0, 0, 0, 122, 0, 0, 0, 73, 109, 112, 111, 114, 116, 0, 0, 70, 105, 108, 101, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 3, 0, 1, 0, 104, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 3, 0, 1, 0, 112, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 3, 0, 1, 0, 132, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 3, 0, 1, 0, 140, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 108, 101, 110, 97, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 109, 112, 111, 114, 116, 115, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 229, 87, 35, 18, 147, 65, 80, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 105, 108, 101, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 160, 93, 146, 118, 241, 43, 234, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_cfea0eb02e810062 = b_cfea0eb02e810062.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_cfea0eb02e810062[] = { &s_ae504193122357e5, &s_f8ea2bf176925da0, }; static const uint16_t m_cfea0eb02e810062[] = {3, 1, 0, 2}; static const uint16_t i_cfea0eb02e810062[] = {0, 1, 2, 3}; const ::capnp::_::RawSchema s_cfea0eb02e810062 = { 0xcfea0eb02e810062, b_cfea0eb02e810062.words, 93, d_cfea0eb02e810062, m_cfea0eb02e810062, 2, 4, i_cfea0eb02e810062, nullptr, nullptr, { &s_cfea0eb02e810062, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<51> b_ae504193122357e5 = { { 0, 0, 0, 0, 5, 0, 6, 0, 229, 87, 35, 18, 147, 65, 80, 174, 48, 0, 0, 0, 1, 0, 1, 0, 98, 0, 129, 46, 176, 14, 234, 207, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 186, 1, 0, 0, 45, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 46, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 46, 73, 109, 112, 111, 114, 116, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 3, 0, 1, 0, 48, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 105, 100, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 97, 109, 101, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_ae504193122357e5 = b_ae504193122357e5.words; #if !CAPNP_LITE static const uint16_t m_ae504193122357e5[] = {0, 1}; static const uint16_t i_ae504193122357e5[] = {0, 1}; const ::capnp::_::RawSchema s_ae504193122357e5 = { 0xae504193122357e5, b_ae504193122357e5.words, 51, nullptr, m_ae504193122357e5, 0, 2, i_ae504193122357e5, nullptr, nullptr, { &s_ae504193122357e5, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<46> b_f8ea2bf176925da0 = { { 0, 0, 0, 0, 5, 0, 6, 0, 160, 93, 146, 118, 241, 43, 234, 248, 48, 0, 0, 0, 1, 0, 0, 0, 98, 0, 129, 46, 176, 14, 234, 207, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 250, 1, 0, 0, 49, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 46, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 46, 70, 105, 108, 101, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0, 187, 153, 4, 46, 137, 25, 167, 221, 1, 0, 0, 0, 90, 0, 0, 0, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 40, 0, 0, 0, 2, 0, 1, 0, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 16, 0, 0, 0, 0, 0, 0, 0, 187, 153, 4, 46, 137, 25, 167, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f8ea2bf176925da0 = b_f8ea2bf176925da0.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_f8ea2bf176925da0[] = { &s_dda719892e0499bb, }; static const uint16_t m_f8ea2bf176925da0[] = {0}; static const uint16_t i_f8ea2bf176925da0[] = {0}; const ::capnp::_::RawSchema s_f8ea2bf176925da0 = { 0xf8ea2bf176925da0, b_f8ea2bf176925da0.words, 46, d_f8ea2bf176925da0, m_f8ea2bf176925da0, 1, 1, i_f8ea2bf176925da0, nullptr, nullptr, { &s_f8ea2bf176925da0, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<78> b_dda719892e0499bb = { { 0, 0, 0, 0, 5, 0, 6, 0, 187, 153, 4, 46, 137, 25, 167, 221, 63, 0, 0, 0, 1, 0, 3, 0, 160, 93, 146, 118, 241, 43, 234, 248, 0, 0, 7, 0, 0, 0, 2, 0, 8, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 82, 2, 0, 0, 57, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 46, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 46, 70, 105, 108, 101, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 46, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 16, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 3, 0, 1, 0, 108, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 3, 0, 1, 0, 112, 0, 0, 0, 2, 0, 1, 0, 2, 0, 255, 255, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 3, 0, 1, 0, 116, 0, 0, 0, 2, 0, 1, 0, 3, 0, 254, 255, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 81, 161, 48, 214, 225, 213, 105, 252, 113, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 116, 97, 114, 116, 66, 121, 116, 101, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 110, 100, 66, 121, 116, 101, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 121, 112, 101, 73, 100, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 101, 109, 98, 101, 114, 0, 0, } }; ::capnp::word const* const bp_dda719892e0499bb = b_dda719892e0499bb.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_dda719892e0499bb[] = { &s_fc69d5e1d630a151, }; static const uint16_t m_dda719892e0499bb[] = {1, 3, 0, 2}; static const uint16_t i_dda719892e0499bb[] = {2, 3, 0, 1}; const ::capnp::_::RawSchema s_dda719892e0499bb = { 0xdda719892e0499bb, b_dda719892e0499bb.words, 78, d_dda719892e0499bb, m_dda719892e0499bb, 1, 4, i_dda719892e0499bb, nullptr, nullptr, { &s_dda719892e0499bb, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<55> b_fc69d5e1d630a151 = { { 0, 0, 0, 0, 5, 0, 6, 0, 81, 161, 48, 214, 225, 213, 105, 252, 74, 0, 0, 0, 1, 0, 3, 0, 187, 153, 4, 46, 137, 25, 167, 221, 0, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 138, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 99, 104, 101, 109, 97, 46, 99, 97, 112, 110, 112, 58, 67, 111, 100, 101, 71, 101, 110, 101, 114, 97, 116, 111, 114, 82, 101, 113, 117, 101, 115, 116, 46, 82, 101, 113, 117, 101, 115, 116, 101, 100, 70, 105, 108, 101, 46, 70, 105, 108, 101, 83, 111, 117, 114, 99, 101, 73, 110, 102, 111, 46, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 46, 109, 101, 109, 98, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 3, 0, 1, 0, 52, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 3, 0, 1, 0, 56, 0, 0, 0, 2, 0, 1, 0, 112, 97, 114, 101, 110, 116, 84, 121, 112, 101, 73, 100, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 114, 100, 105, 110, 97, 108, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_fc69d5e1d630a151 = b_fc69d5e1d630a151.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_fc69d5e1d630a151[] = { &s_dda719892e0499bb, }; static const uint16_t m_fc69d5e1d630a151[] = {1, 0}; static const uint16_t i_fc69d5e1d630a151[] = {0, 1}; const ::capnp::_::RawSchema s_fc69d5e1d630a151 = { 0xfc69d5e1d630a151, b_fc69d5e1d630a151.words, 55, d_fc69d5e1d630a151, m_fc69d5e1d630a151, 1, 2, i_fc69d5e1d630a151, nullptr, nullptr, { &s_fc69d5e1d630a151, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp // ======================================================================================= namespace capnp { namespace schema { // Node #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::_capnpPrivate::dataWordSize; constexpr uint16_t Node::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Parameter #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Parameter::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Parameter::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Parameter::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Parameter::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::NestedNode #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::NestedNode::_capnpPrivate::dataWordSize; constexpr uint16_t Node::NestedNode::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::NestedNode::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::NestedNode::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::SourceInfo #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::SourceInfo::_capnpPrivate::dataWordSize; constexpr uint16_t Node::SourceInfo::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::SourceInfo::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::SourceInfo::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::SourceInfo::Member #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::SourceInfo::Member::_capnpPrivate::dataWordSize; constexpr uint16_t Node::SourceInfo::Member::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::SourceInfo::Member::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::SourceInfo::Member::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Struct #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Struct::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Struct::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Struct::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Struct::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Enum #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Enum::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Enum::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Enum::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Enum::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Interface #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Interface::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Interface::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Interface::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Interface::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Const #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Const::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Const::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Const::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Const::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Node::Annotation #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Node::Annotation::_capnpPrivate::dataWordSize; constexpr uint16_t Node::Annotation::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Node::Annotation::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Node::Annotation::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Field #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Field::_capnpPrivate::dataWordSize; constexpr uint16_t Field::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Field::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Field::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::uint16_t Field::NO_DISCRIMINANT; #endif // Field::Slot #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Field::Slot::_capnpPrivate::dataWordSize; constexpr uint16_t Field::Slot::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Field::Slot::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Field::Slot::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Field::Group #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Field::Group::_capnpPrivate::dataWordSize; constexpr uint16_t Field::Group::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Field::Group::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Field::Group::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Field::Ordinal #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Field::Ordinal::_capnpPrivate::dataWordSize; constexpr uint16_t Field::Ordinal::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Field::Ordinal::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Field::Ordinal::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Enumerant #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Enumerant::_capnpPrivate::dataWordSize; constexpr uint16_t Enumerant::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Enumerant::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Enumerant::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Superclass #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Superclass::_capnpPrivate::dataWordSize; constexpr uint16_t Superclass::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Superclass::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Superclass::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Method #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Method::_capnpPrivate::dataWordSize; constexpr uint16_t Method::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Method::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Method::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::_capnpPrivate::dataWordSize; constexpr uint16_t Type::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::List #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::List::_capnpPrivate::dataWordSize; constexpr uint16_t Type::List::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::List::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::List::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::Enum #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::Enum::_capnpPrivate::dataWordSize; constexpr uint16_t Type::Enum::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::Enum::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::Enum::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::Struct #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::Struct::_capnpPrivate::dataWordSize; constexpr uint16_t Type::Struct::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::Struct::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::Struct::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::Interface #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::Interface::_capnpPrivate::dataWordSize; constexpr uint16_t Type::Interface::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::Interface::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::Interface::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::AnyPointer #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::AnyPointer::_capnpPrivate::dataWordSize; constexpr uint16_t Type::AnyPointer::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::AnyPointer::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::AnyPointer::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::AnyPointer::Unconstrained #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::AnyPointer::Unconstrained::_capnpPrivate::dataWordSize; constexpr uint16_t Type::AnyPointer::Unconstrained::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::AnyPointer::Unconstrained::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::AnyPointer::Unconstrained::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::AnyPointer::Parameter #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::AnyPointer::Parameter::_capnpPrivate::dataWordSize; constexpr uint16_t Type::AnyPointer::Parameter::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::AnyPointer::Parameter::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::AnyPointer::Parameter::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Type::AnyPointer::ImplicitMethodParameter #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::dataWordSize; constexpr uint16_t Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Type::AnyPointer::ImplicitMethodParameter::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Brand #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Brand::_capnpPrivate::dataWordSize; constexpr uint16_t Brand::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Brand::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Brand::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Brand::Scope #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Brand::Scope::_capnpPrivate::dataWordSize; constexpr uint16_t Brand::Scope::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Brand::Scope::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Brand::Scope::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Brand::Binding #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Brand::Binding::_capnpPrivate::dataWordSize; constexpr uint16_t Brand::Binding::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Brand::Binding::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Brand::Binding::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Value #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Value::_capnpPrivate::dataWordSize; constexpr uint16_t Value::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Value::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Value::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // Annotation #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t Annotation::_capnpPrivate::dataWordSize; constexpr uint16_t Annotation::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind Annotation::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* Annotation::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CapnpVersion #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CapnpVersion::_capnpPrivate::dataWordSize; constexpr uint16_t CapnpVersion::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CapnpVersion::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CapnpVersion::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest::RequestedFile #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::RequestedFile::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::RequestedFile::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::RequestedFile::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::RequestedFile::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest::RequestedFile::Import #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::RequestedFile::Import::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::RequestedFile::Import::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::RequestedFile::Import::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::RequestedFile::Import::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest::RequestedFile::FileSourceInfo #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::RequestedFile::FileSourceInfo::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::RequestedFile::FileSourceInfo::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE // CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::_capnpPrivate::dataWordSize; constexpr uint16_t CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::_capnpPrivate::pointerCount; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #if !CAPNP_LITE #if CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL constexpr ::capnp::Kind CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::_capnpPrivate::kind; constexpr ::capnp::_::RawSchema const* CodeGeneratorRequest::RequestedFile::FileSourceInfo::Identifier::Member::_capnpPrivate::schema; #endif // !CAPNP_NEED_REDUNDANT_CONSTEXPR_DECL #endif // !CAPNP_LITE } // namespace } // namespace capnproto-c++-1.1.0/src/capnp/llvm-fuzzer-testcase.c++0000644000175000017500000000174414712011043023231 0ustar00kentonkenton00000000000000#include "test-util.h" #include #include "serialize.h" #include #include /* This is the entry point of a fuzz target to be used with libFuzzer * or another fuzz driver. * Such a fuzz driver is used by the autotools target capnp-llvm-fuzzer-testcase * when the environment variable LIB_FUZZING_ENGINE is defined * for instance LIB_FUZZING_ENGINE=-fsanitize=fuzzer for libFuzzer */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { kj::ArrayPtr array(Data, Size); kj::ArrayInputStream ais(array); KJ_IF_MAYBE(e, kj::runCatchingExceptions([&]() { capnp::InputStreamMessageReader reader(ais); capnp::_::checkTestMessage(reader.getRoot()); capnp::_::checkDynamicTestMessage(reader.getRoot(capnp::Schema::from())); kj::str(reader.getRoot()); })) { KJ_LOG(ERROR, "threw"); } return 0; } capnproto-c++-1.1.0/src/capnp/schema-loader.h0000644000175000017500000002212214527152321021510 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "schema.h" #include #include CAPNP_BEGIN_HEADER namespace capnp { class SchemaLoader { // Class which can be used to construct Schema objects from schema::Nodes as defined in // schema.capnp. // // It is a bad idea to use this class on untrusted input with exceptions disabled -- you may // be exposing yourself to denial-of-service attacks, as attackers can easily construct schemas // that are subtly inconsistent in a way that causes exceptions to be thrown either by // SchemaLoader or by the dynamic API when the schemas are subsequently used. If you enable and // properly catch exceptions, you should be OK -- assuming no bugs in the Cap'n Proto // implementation, of course. public: class LazyLoadCallback { public: virtual void load(const SchemaLoader& loader, uint64_t id) const = 0; // Request that the schema node with the given ID be loaded into the given SchemaLoader. If // the callback is able to find a schema for this ID, it should invoke `loadOnce()` on // `loader` to load it. If no such node exists, it should simply do nothing and return. // // The callback is allowed to load schema nodes other than the one requested, e.g. because it // expects they will be needed soon. // // If the `SchemaLoader` is used from multiple threads, the callback must be thread-safe. // In particular, it's possible for multiple threads to invoke `load()` with the same ID. // If the callback performs a large amount of work to look up IDs, it should be sure to // de-dup these requests. }; SchemaLoader(); SchemaLoader(const LazyLoadCallback& callback); // Construct a SchemaLoader which will invoke the given callback when a schema node is requested // that isn't already loaded. ~SchemaLoader() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(SchemaLoader); Schema get(uint64_t id, schema::Brand::Reader brand = schema::Brand::Reader(), Schema scope = Schema()) const; // Gets the schema for the given ID, throwing an exception if it isn't present. // // The returned schema may be invalidated if load() is called with a new schema for the same ID. // In general, you should not call load() while a schema from this loader is in-use. // // `brand` and `scope` are used to determine brand bindings where relevant. `brand` gives // parameter bindings for the target type's brand parameters that were specified at the reference // site. `scope` specifies the scope in which the type ID appeared -- if `brand` itself contains // parameter references or indicates that some parameters will be inherited, these will be // interpreted within / inherited from `scope`. kj::Maybe tryGet(uint64_t id, schema::Brand::Reader bindings = schema::Brand::Reader(), Schema scope = Schema()) const; // Like get() but doesn't throw. Schema getUnbound(uint64_t id) const; // Gets a special version of the schema in which all brand parameters are "unbound". This means // that if you look up a type via the Schema API, and it resolves to a brand parameter, the // returned Type's getBrandParameter() method will return info about that parameter. Otherwise, // normally, all brand parameters that aren't otherwise bound are assumed to simply be // "AnyPointer". Type getType(schema::Type::Reader type, Schema scope = Schema()) const; // Convenience method which interprets a schema::Type to produce a Type object. Implemented in // terms of get(). Schema load(const schema::Node::Reader& reader); // Loads the given schema node. Validates the node and throws an exception if invalid. This // makes a copy of the schema, so the object passed in can be destroyed after this returns. // // If the node has any dependencies which are not already loaded, they will be initialized as // stubs -- empty schemas of whichever kind is expected. // // If another schema for the given reader has already been seen, the loader will inspect both // schemas to determine which one is newer, and use that that one. If the two versions are // found to be incompatible, an exception is thrown. If the two versions differ but are // compatible and the loader cannot determine which is newer (e.g., the only changes are renames), // the existing schema will be preferred. Note that in any case, the loader will end up keeping // around copies of both schemas, so you shouldn't repeatedly reload schemas into the same loader. // // The following properties of the schema node are validated: // - Struct size and preferred list encoding are valid and consistent. // - Struct members are fields or unions. // - Union members are fields. // - Field offsets are in-bounds. // - Ordinals and codeOrders are sequential starting from zero. // - Values are of the right union case to match their types. // // You should assume anything not listed above is NOT validated. In particular, things that are // not validated now, but could be in the future, include but are not limited to: // - Names. // - Annotation values. (This is hard because the annotation declaration is not always // available.) // - Content of default/constant values of pointer type. (Validating these would require knowing // their schema, but even if the schemas are available at validation time, they could be // updated by a subsequent load(), invalidating existing values. Instead, these values are // validated at the time they are used, as usual for Cap'n Proto objects.) // // Also note that unknown types are not considered invalid. Instead, the dynamic API returns // a DynamicValue with type UNKNOWN for these. Schema loadOnce(const schema::Node::Reader& reader) const; // Like `load()` but does nothing if a schema with the same ID is already loaded. In contrast, // `load()` would attempt to compare the schemas and take the newer one. `loadOnce()` is safe // to call even while concurrently using schemas from this loader. It should be considered an // error to call `loadOnce()` with two non-identical schemas that share the same ID, although // this error may or may not actually be detected by the implementation. template void loadCompiledTypeAndDependencies(); // Load the schema for the given compiled-in type and all of its dependencies. // // If you want to be able to cast a DynamicValue built from this SchemaLoader to the compiled-in // type using as(), you must call this method before constructing the DynamicValue. Otherwise, // as() will throw an exception complaining about type mismatch. kj::Array getAllLoaded() const; // Get a complete list of all loaded schema nodes. It is particularly useful to call this after // loadCompiledTypeAndDependencies() in order to get a flat list of all of T's transitive // dependencies. void computeOptimizationHints(); // Call after all interesting schemas have been loaded to compute optimization hints. In // particular, this initializes `hasNoCapabilities` for every struct type. Before this is called, // that value is initialized to false for all types (which ensures correct behavior but does not // allow the optimization). // // If any loaded struct types contain fields of types for which no schema has been loaded, they // will be presumed to possibly contain capabilities. `LazyLoadCallback` will NOT be invoked to // load any types that haven't been loaded yet. // // TODO(someday): Perhaps we could dynamically initialize the hints on-demand, but it would be // much more work to implement. private: class Validator; class CompatibilityChecker; class Impl; class InitializerImpl; class BrandedInitializerImpl; kj::MutexGuarded> impl; void loadNative(const _::RawSchema* nativeSchema); }; template inline void SchemaLoader::loadCompiledTypeAndDependencies() { loadNative(&_::rawSchema()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/rpc-prelude.h0000644000175000017500000000717714712011043021232 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // This file contains a bunch of internal declarations that must appear before rpc.h can start. // We don't define these directly in rpc.h because it makes the file hard to read. #pragma once #include #include "persistent.capnp.h" CAPNP_BEGIN_HEADER namespace capnp { class OutgoingRpcMessage; class IncomingRpcMessage; class RpcFlowController; template class RpcSystem; namespace _ { // private class VatNetworkBase { // Non-template version of VatNetwork. Ignore this class; see VatNetwork in rpc.h. public: class Connection; struct ConnectionAndProvisionId { kj::Own connection; kj::Own firstMessage; Orphan provisionId; }; class Connection { public: virtual kj::Own newOutgoingMessage(uint firstSegmentWordSize) = 0; virtual kj::Promise>> receiveIncomingMessage() = 0; virtual kj::Promise shutdown() = 0; virtual AnyStruct::Reader baseGetPeerVatId() = 0; virtual kj::Own newStream() = 0; }; virtual kj::Maybe> baseConnect(AnyStruct::Reader vatId) = 0; virtual kj::Promise> baseAccept() = 0; }; class SturdyRefRestorerBase { public: virtual Capability::Client baseRestore(AnyPointer::Reader ref) = 0; }; class BootstrapFactoryBase { // Non-template version of BootstrapFactory. Ignore this class; see BootstrapFactory in rpc.h. public: virtual Capability::Client baseCreateFor(AnyStruct::Reader clientId) = 0; }; class RpcSystemBase { // Non-template version of RpcSystem. Ignore this class; see RpcSystem in rpc.h. public: RpcSystemBase(VatNetworkBase& network, kj::Maybe bootstrapInterface); RpcSystemBase(VatNetworkBase& network, BootstrapFactoryBase& bootstrapFactory); RpcSystemBase(VatNetworkBase& network, SturdyRefRestorerBase& restorer); RpcSystemBase(RpcSystemBase&& other) noexcept; ~RpcSystemBase() noexcept(false); void setTraceEncoder(kj::Function func); kj::Promise run(); private: class Impl; kj::Own impl; Capability::Client baseBootstrap(AnyStruct::Reader vatId); Capability::Client baseRestore(AnyStruct::Reader vatId, AnyPointer::Reader objectId); void baseSetFlowLimit(size_t words); template friend class capnp::RpcSystem; }; } // namespace _ (private) } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/rpc.capnp.h0000644000175000017500000056523414731562162020715 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: rpc.capnp #pragma once #include #include #ifndef CAPNP_VERSION #error "CAPNP_VERSION is not defined, is capnp/generated-header-support.h missing?" #elif CAPNP_VERSION != 1001000 #error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." #endif CAPNP_BEGIN_HEADER namespace capnp { namespace schemas { CAPNP_DECLARE_SCHEMA(91b79f1f808db032); CAPNP_DECLARE_SCHEMA(e94ccf8031176ec4); CAPNP_DECLARE_SCHEMA(836a53ce789d4cd4); CAPNP_DECLARE_SCHEMA(dae8b0f61aab5f99); CAPNP_DECLARE_SCHEMA(9e19b28d3db3573a); CAPNP_DECLARE_SCHEMA(d37d2eb2c2f80e63); CAPNP_DECLARE_SCHEMA(bbc29655fa89086e); CAPNP_DECLARE_SCHEMA(ad1a6c0d7dd07497); CAPNP_DECLARE_SCHEMA(f964368b0fbd3711); CAPNP_DECLARE_SCHEMA(d562b4df655bdd4d); CAPNP_DECLARE_SCHEMA(9c6a046bfbc1ac5a); CAPNP_DECLARE_SCHEMA(d4c9b56290554016); CAPNP_DECLARE_SCHEMA(fbe1980490e001af); CAPNP_DECLARE_SCHEMA(95bc14545813fbc1); CAPNP_DECLARE_SCHEMA(9a0e61223d96743b); CAPNP_DECLARE_SCHEMA(8523ddc40b86b8b0); CAPNP_DECLARE_SCHEMA(d800b1d6cd6f1ca0); CAPNP_DECLARE_SCHEMA(f316944415569081); CAPNP_DECLARE_SCHEMA(d37007fde1f0027d); CAPNP_DECLARE_SCHEMA(d625b7063acf691a); CAPNP_DECLARE_SCHEMA(b28c96e23f4cbd58); enum class Type_b28c96e23f4cbd58: uint16_t { FAILED, OVERLOADED, DISCONNECTED, UNIMPLEMENTED, }; CAPNP_DECLARE_ENUM(Type, b28c96e23f4cbd58); } // namespace schemas } // namespace capnp namespace capnp { namespace rpc { struct Message { Message() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { UNIMPLEMENTED, ABORT, CALL, RETURN, FINISH, RESOLVE, RELEASE, OBSOLETE_SAVE, BOOTSTRAP, OBSOLETE_DELETE, PROVIDE, ACCEPT, JOIN, DISEMBARGO, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(91b79f1f808db032, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Bootstrap { Bootstrap() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(e94ccf8031176ec4, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Call { Call() = delete; class Reader; class Builder; class Pipeline; struct SendResultsTo; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(836a53ce789d4cd4, 3, 3) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Call::SendResultsTo { SendResultsTo() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { CALLER, YOURSELF, THIRD_PARTY, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(dae8b0f61aab5f99, 3, 3) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Return { Return() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { RESULTS, EXCEPTION, CANCELED, RESULTS_SENT_ELSEWHERE, TAKE_FROM_OTHER_QUESTION, ACCEPT_FROM_THIRD_PARTY, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9e19b28d3db3573a, 2, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Finish { Finish() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d37d2eb2c2f80e63, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Resolve { Resolve() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { CAP, EXCEPTION, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(bbc29655fa89086e, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Release { Release() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(ad1a6c0d7dd07497, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Disembargo { Disembargo() = delete; class Reader; class Builder; class Pipeline; struct Context; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f964368b0fbd3711, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Disembargo::Context { Context() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { SENDER_LOOPBACK, RECEIVER_LOOPBACK, ACCEPT, PROVIDE, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d562b4df655bdd4d, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Provide { Provide() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9c6a046bfbc1ac5a, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Accept { Accept() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d4c9b56290554016, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Join { Join() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(fbe1980490e001af, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct MessageTarget { MessageTarget() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { IMPORTED_CAP, PROMISED_ANSWER, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(95bc14545813fbc1, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Payload { Payload() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(9a0e61223d96743b, 0, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct CapDescriptor { CapDescriptor() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NONE, SENDER_HOSTED, SENDER_PROMISE, RECEIVER_HOSTED, RECEIVER_ANSWER, THIRD_PARTY_HOSTED, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(8523ddc40b86b8b0, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct PromisedAnswer { PromisedAnswer() = delete; class Reader; class Builder; class Pipeline; struct Op; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d800b1d6cd6f1ca0, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct PromisedAnswer::Op { Op() = delete; class Reader; class Builder; class Pipeline; enum Which: uint16_t { NOOP, GET_POINTER_FIELD, }; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(f316944415569081, 1, 0) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct ThirdPartyCapDescriptor { ThirdPartyCapDescriptor() = delete; class Reader; class Builder; class Pipeline; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d37007fde1f0027d, 1, 1) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; struct Exception { Exception() = delete; class Reader; class Builder; class Pipeline; typedef ::capnp::schemas::Type_b28c96e23f4cbd58 Type; struct _capnpPrivate { CAPNP_DECLARE_STRUCT_HEADER(d625b7063acf691a, 1, 2) #if !CAPNP_LITE static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } #endif // !CAPNP_LITE }; }; // ======================================================================================= class Message::Reader { public: typedef Message Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isUnimplemented() const; inline bool hasUnimplemented() const; inline ::capnp::rpc::Message::Reader getUnimplemented() const; inline bool isAbort() const; inline bool hasAbort() const; inline ::capnp::rpc::Exception::Reader getAbort() const; inline bool isCall() const; inline bool hasCall() const; inline ::capnp::rpc::Call::Reader getCall() const; inline bool isReturn() const; inline bool hasReturn() const; inline ::capnp::rpc::Return::Reader getReturn() const; inline bool isFinish() const; inline bool hasFinish() const; inline ::capnp::rpc::Finish::Reader getFinish() const; inline bool isResolve() const; inline bool hasResolve() const; inline ::capnp::rpc::Resolve::Reader getResolve() const; inline bool isRelease() const; inline bool hasRelease() const; inline ::capnp::rpc::Release::Reader getRelease() const; inline bool isObsoleteSave() const; inline bool hasObsoleteSave() const; inline ::capnp::AnyPointer::Reader getObsoleteSave() const; inline bool isBootstrap() const; inline bool hasBootstrap() const; inline ::capnp::rpc::Bootstrap::Reader getBootstrap() const; inline bool isObsoleteDelete() const; inline bool hasObsoleteDelete() const; inline ::capnp::AnyPointer::Reader getObsoleteDelete() const; inline bool isProvide() const; inline bool hasProvide() const; inline ::capnp::rpc::Provide::Reader getProvide() const; inline bool isAccept() const; inline bool hasAccept() const; inline ::capnp::rpc::Accept::Reader getAccept() const; inline bool isJoin() const; inline bool hasJoin() const; inline ::capnp::rpc::Join::Reader getJoin() const; inline bool isDisembargo() const; inline bool hasDisembargo() const; inline ::capnp::rpc::Disembargo::Reader getDisembargo() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Message::Builder { public: typedef Message Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isUnimplemented(); inline bool hasUnimplemented(); inline ::capnp::rpc::Message::Builder getUnimplemented(); inline void setUnimplemented( ::capnp::rpc::Message::Reader value); inline ::capnp::rpc::Message::Builder initUnimplemented(); inline void adoptUnimplemented(::capnp::Orphan< ::capnp::rpc::Message>&& value); inline ::capnp::Orphan< ::capnp::rpc::Message> disownUnimplemented(); inline bool isAbort(); inline bool hasAbort(); inline ::capnp::rpc::Exception::Builder getAbort(); inline void setAbort( ::capnp::rpc::Exception::Reader value); inline ::capnp::rpc::Exception::Builder initAbort(); inline void adoptAbort(::capnp::Orphan< ::capnp::rpc::Exception>&& value); inline ::capnp::Orphan< ::capnp::rpc::Exception> disownAbort(); inline bool isCall(); inline bool hasCall(); inline ::capnp::rpc::Call::Builder getCall(); inline void setCall( ::capnp::rpc::Call::Reader value); inline ::capnp::rpc::Call::Builder initCall(); inline void adoptCall(::capnp::Orphan< ::capnp::rpc::Call>&& value); inline ::capnp::Orphan< ::capnp::rpc::Call> disownCall(); inline bool isReturn(); inline bool hasReturn(); inline ::capnp::rpc::Return::Builder getReturn(); inline void setReturn( ::capnp::rpc::Return::Reader value); inline ::capnp::rpc::Return::Builder initReturn(); inline void adoptReturn(::capnp::Orphan< ::capnp::rpc::Return>&& value); inline ::capnp::Orphan< ::capnp::rpc::Return> disownReturn(); inline bool isFinish(); inline bool hasFinish(); inline ::capnp::rpc::Finish::Builder getFinish(); inline void setFinish( ::capnp::rpc::Finish::Reader value); inline ::capnp::rpc::Finish::Builder initFinish(); inline void adoptFinish(::capnp::Orphan< ::capnp::rpc::Finish>&& value); inline ::capnp::Orphan< ::capnp::rpc::Finish> disownFinish(); inline bool isResolve(); inline bool hasResolve(); inline ::capnp::rpc::Resolve::Builder getResolve(); inline void setResolve( ::capnp::rpc::Resolve::Reader value); inline ::capnp::rpc::Resolve::Builder initResolve(); inline void adoptResolve(::capnp::Orphan< ::capnp::rpc::Resolve>&& value); inline ::capnp::Orphan< ::capnp::rpc::Resolve> disownResolve(); inline bool isRelease(); inline bool hasRelease(); inline ::capnp::rpc::Release::Builder getRelease(); inline void setRelease( ::capnp::rpc::Release::Reader value); inline ::capnp::rpc::Release::Builder initRelease(); inline void adoptRelease(::capnp::Orphan< ::capnp::rpc::Release>&& value); inline ::capnp::Orphan< ::capnp::rpc::Release> disownRelease(); inline bool isObsoleteSave(); inline bool hasObsoleteSave(); inline ::capnp::AnyPointer::Builder getObsoleteSave(); inline ::capnp::AnyPointer::Builder initObsoleteSave(); inline bool isBootstrap(); inline bool hasBootstrap(); inline ::capnp::rpc::Bootstrap::Builder getBootstrap(); inline void setBootstrap( ::capnp::rpc::Bootstrap::Reader value); inline ::capnp::rpc::Bootstrap::Builder initBootstrap(); inline void adoptBootstrap(::capnp::Orphan< ::capnp::rpc::Bootstrap>&& value); inline ::capnp::Orphan< ::capnp::rpc::Bootstrap> disownBootstrap(); inline bool isObsoleteDelete(); inline bool hasObsoleteDelete(); inline ::capnp::AnyPointer::Builder getObsoleteDelete(); inline ::capnp::AnyPointer::Builder initObsoleteDelete(); inline bool isProvide(); inline bool hasProvide(); inline ::capnp::rpc::Provide::Builder getProvide(); inline void setProvide( ::capnp::rpc::Provide::Reader value); inline ::capnp::rpc::Provide::Builder initProvide(); inline void adoptProvide(::capnp::Orphan< ::capnp::rpc::Provide>&& value); inline ::capnp::Orphan< ::capnp::rpc::Provide> disownProvide(); inline bool isAccept(); inline bool hasAccept(); inline ::capnp::rpc::Accept::Builder getAccept(); inline void setAccept( ::capnp::rpc::Accept::Reader value); inline ::capnp::rpc::Accept::Builder initAccept(); inline void adoptAccept(::capnp::Orphan< ::capnp::rpc::Accept>&& value); inline ::capnp::Orphan< ::capnp::rpc::Accept> disownAccept(); inline bool isJoin(); inline bool hasJoin(); inline ::capnp::rpc::Join::Builder getJoin(); inline void setJoin( ::capnp::rpc::Join::Reader value); inline ::capnp::rpc::Join::Builder initJoin(); inline void adoptJoin(::capnp::Orphan< ::capnp::rpc::Join>&& value); inline ::capnp::Orphan< ::capnp::rpc::Join> disownJoin(); inline bool isDisembargo(); inline bool hasDisembargo(); inline ::capnp::rpc::Disembargo::Builder getDisembargo(); inline void setDisembargo( ::capnp::rpc::Disembargo::Reader value); inline ::capnp::rpc::Disembargo::Builder initDisembargo(); inline void adoptDisembargo(::capnp::Orphan< ::capnp::rpc::Disembargo>&& value); inline ::capnp::Orphan< ::capnp::rpc::Disembargo> disownDisembargo(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Message::Pipeline { public: typedef Message Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Bootstrap::Reader { public: typedef Bootstrap Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasDeprecatedObjectId() const; inline ::capnp::AnyPointer::Reader getDeprecatedObjectId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Bootstrap::Builder { public: typedef Bootstrap Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasDeprecatedObjectId(); inline ::capnp::AnyPointer::Builder getDeprecatedObjectId(); inline ::capnp::AnyPointer::Builder initDeprecatedObjectId(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Bootstrap::Pipeline { public: typedef Bootstrap Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Call::Reader { public: typedef Call Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasTarget() const; inline ::capnp::rpc::MessageTarget::Reader getTarget() const; inline ::uint64_t getInterfaceId() const; inline ::uint16_t getMethodId() const; inline bool hasParams() const; inline ::capnp::rpc::Payload::Reader getParams() const; inline typename SendResultsTo::Reader getSendResultsTo() const; inline bool getAllowThirdPartyTailCall() const; inline bool getNoPromisePipelining() const; inline bool getOnlyPromisePipeline() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Call::Builder { public: typedef Call Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasTarget(); inline ::capnp::rpc::MessageTarget::Builder getTarget(); inline void setTarget( ::capnp::rpc::MessageTarget::Reader value); inline ::capnp::rpc::MessageTarget::Builder initTarget(); inline void adoptTarget(::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value); inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> disownTarget(); inline ::uint64_t getInterfaceId(); inline void setInterfaceId( ::uint64_t value); inline ::uint16_t getMethodId(); inline void setMethodId( ::uint16_t value); inline bool hasParams(); inline ::capnp::rpc::Payload::Builder getParams(); inline void setParams( ::capnp::rpc::Payload::Reader value); inline ::capnp::rpc::Payload::Builder initParams(); inline void adoptParams(::capnp::Orphan< ::capnp::rpc::Payload>&& value); inline ::capnp::Orphan< ::capnp::rpc::Payload> disownParams(); inline typename SendResultsTo::Builder getSendResultsTo(); inline typename SendResultsTo::Builder initSendResultsTo(); inline bool getAllowThirdPartyTailCall(); inline void setAllowThirdPartyTailCall(bool value); inline bool getNoPromisePipelining(); inline void setNoPromisePipelining(bool value); inline bool getOnlyPromisePipeline(); inline void setOnlyPromisePipeline(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Call::Pipeline { public: typedef Call Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::rpc::MessageTarget::Pipeline getTarget(); inline ::capnp::rpc::Payload::Pipeline getParams(); inline typename SendResultsTo::Pipeline getSendResultsTo(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Call::SendResultsTo::Reader { public: typedef SendResultsTo Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isCaller() const; inline ::capnp::Void getCaller() const; inline bool isYourself() const; inline ::capnp::Void getYourself() const; inline bool isThirdParty() const; inline bool hasThirdParty() const; inline ::capnp::AnyPointer::Reader getThirdParty() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Call::SendResultsTo::Builder { public: typedef SendResultsTo Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isCaller(); inline ::capnp::Void getCaller(); inline void setCaller( ::capnp::Void value = ::capnp::VOID); inline bool isYourself(); inline ::capnp::Void getYourself(); inline void setYourself( ::capnp::Void value = ::capnp::VOID); inline bool isThirdParty(); inline bool hasThirdParty(); inline ::capnp::AnyPointer::Builder getThirdParty(); inline ::capnp::AnyPointer::Builder initThirdParty(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Call::SendResultsTo::Pipeline { public: typedef SendResultsTo Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Return::Reader { public: typedef Return Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline ::uint32_t getAnswerId() const; inline bool getReleaseParamCaps() const; inline bool isResults() const; inline bool hasResults() const; inline ::capnp::rpc::Payload::Reader getResults() const; inline bool isException() const; inline bool hasException() const; inline ::capnp::rpc::Exception::Reader getException() const; inline bool isCanceled() const; inline ::capnp::Void getCanceled() const; inline bool isResultsSentElsewhere() const; inline ::capnp::Void getResultsSentElsewhere() const; inline bool isTakeFromOtherQuestion() const; inline ::uint32_t getTakeFromOtherQuestion() const; inline bool isAcceptFromThirdParty() const; inline bool hasAcceptFromThirdParty() const; inline ::capnp::AnyPointer::Reader getAcceptFromThirdParty() const; inline bool getNoFinishNeeded() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Return::Builder { public: typedef Return Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline ::uint32_t getAnswerId(); inline void setAnswerId( ::uint32_t value); inline bool getReleaseParamCaps(); inline void setReleaseParamCaps(bool value); inline bool isResults(); inline bool hasResults(); inline ::capnp::rpc::Payload::Builder getResults(); inline void setResults( ::capnp::rpc::Payload::Reader value); inline ::capnp::rpc::Payload::Builder initResults(); inline void adoptResults(::capnp::Orphan< ::capnp::rpc::Payload>&& value); inline ::capnp::Orphan< ::capnp::rpc::Payload> disownResults(); inline bool isException(); inline bool hasException(); inline ::capnp::rpc::Exception::Builder getException(); inline void setException( ::capnp::rpc::Exception::Reader value); inline ::capnp::rpc::Exception::Builder initException(); inline void adoptException(::capnp::Orphan< ::capnp::rpc::Exception>&& value); inline ::capnp::Orphan< ::capnp::rpc::Exception> disownException(); inline bool isCanceled(); inline ::capnp::Void getCanceled(); inline void setCanceled( ::capnp::Void value = ::capnp::VOID); inline bool isResultsSentElsewhere(); inline ::capnp::Void getResultsSentElsewhere(); inline void setResultsSentElsewhere( ::capnp::Void value = ::capnp::VOID); inline bool isTakeFromOtherQuestion(); inline ::uint32_t getTakeFromOtherQuestion(); inline void setTakeFromOtherQuestion( ::uint32_t value); inline bool isAcceptFromThirdParty(); inline bool hasAcceptFromThirdParty(); inline ::capnp::AnyPointer::Builder getAcceptFromThirdParty(); inline ::capnp::AnyPointer::Builder initAcceptFromThirdParty(); inline bool getNoFinishNeeded(); inline void setNoFinishNeeded(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Return::Pipeline { public: typedef Return Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Finish::Reader { public: typedef Finish Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool getReleaseResultCaps() const; inline bool getRequireEarlyCancellationWorkaround() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Finish::Builder { public: typedef Finish Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool getReleaseResultCaps(); inline void setReleaseResultCaps(bool value); inline bool getRequireEarlyCancellationWorkaround(); inline void setRequireEarlyCancellationWorkaround(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Finish::Pipeline { public: typedef Finish Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Resolve::Reader { public: typedef Resolve Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline ::uint32_t getPromiseId() const; inline bool isCap() const; inline bool hasCap() const; inline ::capnp::rpc::CapDescriptor::Reader getCap() const; inline bool isException() const; inline bool hasException() const; inline ::capnp::rpc::Exception::Reader getException() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Resolve::Builder { public: typedef Resolve Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline ::uint32_t getPromiseId(); inline void setPromiseId( ::uint32_t value); inline bool isCap(); inline bool hasCap(); inline ::capnp::rpc::CapDescriptor::Builder getCap(); inline void setCap( ::capnp::rpc::CapDescriptor::Reader value); inline ::capnp::rpc::CapDescriptor::Builder initCap(); inline void adoptCap(::capnp::Orphan< ::capnp::rpc::CapDescriptor>&& value); inline ::capnp::Orphan< ::capnp::rpc::CapDescriptor> disownCap(); inline bool isException(); inline bool hasException(); inline ::capnp::rpc::Exception::Builder getException(); inline void setException( ::capnp::rpc::Exception::Reader value); inline ::capnp::rpc::Exception::Builder initException(); inline void adoptException(::capnp::Orphan< ::capnp::rpc::Exception>&& value); inline ::capnp::Orphan< ::capnp::rpc::Exception> disownException(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Resolve::Pipeline { public: typedef Resolve Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Release::Reader { public: typedef Release Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getId() const; inline ::uint32_t getReferenceCount() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Release::Builder { public: typedef Release Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getId(); inline void setId( ::uint32_t value); inline ::uint32_t getReferenceCount(); inline void setReferenceCount( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Release::Pipeline { public: typedef Release Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Disembargo::Reader { public: typedef Disembargo Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasTarget() const; inline ::capnp::rpc::MessageTarget::Reader getTarget() const; inline typename Context::Reader getContext() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Disembargo::Builder { public: typedef Disembargo Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasTarget(); inline ::capnp::rpc::MessageTarget::Builder getTarget(); inline void setTarget( ::capnp::rpc::MessageTarget::Reader value); inline ::capnp::rpc::MessageTarget::Builder initTarget(); inline void adoptTarget(::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value); inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> disownTarget(); inline typename Context::Builder getContext(); inline typename Context::Builder initContext(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Disembargo::Pipeline { public: typedef Disembargo Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::rpc::MessageTarget::Pipeline getTarget(); inline typename Context::Pipeline getContext(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Disembargo::Context::Reader { public: typedef Context Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isSenderLoopback() const; inline ::uint32_t getSenderLoopback() const; inline bool isReceiverLoopback() const; inline ::uint32_t getReceiverLoopback() const; inline bool isAccept() const; inline ::capnp::Void getAccept() const; inline bool isProvide() const; inline ::uint32_t getProvide() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Disembargo::Context::Builder { public: typedef Context Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isSenderLoopback(); inline ::uint32_t getSenderLoopback(); inline void setSenderLoopback( ::uint32_t value); inline bool isReceiverLoopback(); inline ::uint32_t getReceiverLoopback(); inline void setReceiverLoopback( ::uint32_t value); inline bool isAccept(); inline ::capnp::Void getAccept(); inline void setAccept( ::capnp::Void value = ::capnp::VOID); inline bool isProvide(); inline ::uint32_t getProvide(); inline void setProvide( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Disembargo::Context::Pipeline { public: typedef Context Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Provide::Reader { public: typedef Provide Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasTarget() const; inline ::capnp::rpc::MessageTarget::Reader getTarget() const; inline bool hasRecipient() const; inline ::capnp::AnyPointer::Reader getRecipient() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Provide::Builder { public: typedef Provide Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasTarget(); inline ::capnp::rpc::MessageTarget::Builder getTarget(); inline void setTarget( ::capnp::rpc::MessageTarget::Reader value); inline ::capnp::rpc::MessageTarget::Builder initTarget(); inline void adoptTarget(::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value); inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> disownTarget(); inline bool hasRecipient(); inline ::capnp::AnyPointer::Builder getRecipient(); inline ::capnp::AnyPointer::Builder initRecipient(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Provide::Pipeline { public: typedef Provide Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::rpc::MessageTarget::Pipeline getTarget(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Accept::Reader { public: typedef Accept Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasProvision() const; inline ::capnp::AnyPointer::Reader getProvision() const; inline bool getEmbargo() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Accept::Builder { public: typedef Accept Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasProvision(); inline ::capnp::AnyPointer::Builder getProvision(); inline ::capnp::AnyPointer::Builder initProvision(); inline bool getEmbargo(); inline void setEmbargo(bool value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Accept::Pipeline { public: typedef Accept Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Join::Reader { public: typedef Join Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasTarget() const; inline ::capnp::rpc::MessageTarget::Reader getTarget() const; inline bool hasKeyPart() const; inline ::capnp::AnyPointer::Reader getKeyPart() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Join::Builder { public: typedef Join Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasTarget(); inline ::capnp::rpc::MessageTarget::Builder getTarget(); inline void setTarget( ::capnp::rpc::MessageTarget::Reader value); inline ::capnp::rpc::MessageTarget::Builder initTarget(); inline void adoptTarget(::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value); inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> disownTarget(); inline bool hasKeyPart(); inline ::capnp::AnyPointer::Builder getKeyPart(); inline ::capnp::AnyPointer::Builder initKeyPart(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Join::Pipeline { public: typedef Join Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} inline ::capnp::rpc::MessageTarget::Pipeline getTarget(); private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class MessageTarget::Reader { public: typedef MessageTarget Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isImportedCap() const; inline ::uint32_t getImportedCap() const; inline bool isPromisedAnswer() const; inline bool hasPromisedAnswer() const; inline ::capnp::rpc::PromisedAnswer::Reader getPromisedAnswer() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class MessageTarget::Builder { public: typedef MessageTarget Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isImportedCap(); inline ::uint32_t getImportedCap(); inline void setImportedCap( ::uint32_t value); inline bool isPromisedAnswer(); inline bool hasPromisedAnswer(); inline ::capnp::rpc::PromisedAnswer::Builder getPromisedAnswer(); inline void setPromisedAnswer( ::capnp::rpc::PromisedAnswer::Reader value); inline ::capnp::rpc::PromisedAnswer::Builder initPromisedAnswer(); inline void adoptPromisedAnswer(::capnp::Orphan< ::capnp::rpc::PromisedAnswer>&& value); inline ::capnp::Orphan< ::capnp::rpc::PromisedAnswer> disownPromisedAnswer(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class MessageTarget::Pipeline { public: typedef MessageTarget Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Payload::Reader { public: typedef Payload Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasContent() const; inline ::capnp::AnyPointer::Reader getContent() const; inline bool hasCapTable() const; inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Reader getCapTable() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Payload::Builder { public: typedef Payload Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasContent(); inline ::capnp::AnyPointer::Builder getContent(); inline ::capnp::AnyPointer::Builder initContent(); inline bool hasCapTable(); inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Builder getCapTable(); inline void setCapTable( ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Builder initCapTable(unsigned int size); inline void adoptCapTable(::capnp::Orphan< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>> disownCapTable(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Payload::Pipeline { public: typedef Payload Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class CapDescriptor::Reader { public: typedef CapDescriptor Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNone() const; inline ::capnp::Void getNone() const; inline bool isSenderHosted() const; inline ::uint32_t getSenderHosted() const; inline bool isSenderPromise() const; inline ::uint32_t getSenderPromise() const; inline bool isReceiverHosted() const; inline ::uint32_t getReceiverHosted() const; inline bool isReceiverAnswer() const; inline bool hasReceiverAnswer() const; inline ::capnp::rpc::PromisedAnswer::Reader getReceiverAnswer() const; inline bool isThirdPartyHosted() const; inline bool hasThirdPartyHosted() const; inline ::capnp::rpc::ThirdPartyCapDescriptor::Reader getThirdPartyHosted() const; inline ::uint8_t getAttachedFd() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class CapDescriptor::Builder { public: typedef CapDescriptor Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNone(); inline ::capnp::Void getNone(); inline void setNone( ::capnp::Void value = ::capnp::VOID); inline bool isSenderHosted(); inline ::uint32_t getSenderHosted(); inline void setSenderHosted( ::uint32_t value); inline bool isSenderPromise(); inline ::uint32_t getSenderPromise(); inline void setSenderPromise( ::uint32_t value); inline bool isReceiverHosted(); inline ::uint32_t getReceiverHosted(); inline void setReceiverHosted( ::uint32_t value); inline bool isReceiverAnswer(); inline bool hasReceiverAnswer(); inline ::capnp::rpc::PromisedAnswer::Builder getReceiverAnswer(); inline void setReceiverAnswer( ::capnp::rpc::PromisedAnswer::Reader value); inline ::capnp::rpc::PromisedAnswer::Builder initReceiverAnswer(); inline void adoptReceiverAnswer(::capnp::Orphan< ::capnp::rpc::PromisedAnswer>&& value); inline ::capnp::Orphan< ::capnp::rpc::PromisedAnswer> disownReceiverAnswer(); inline bool isThirdPartyHosted(); inline bool hasThirdPartyHosted(); inline ::capnp::rpc::ThirdPartyCapDescriptor::Builder getThirdPartyHosted(); inline void setThirdPartyHosted( ::capnp::rpc::ThirdPartyCapDescriptor::Reader value); inline ::capnp::rpc::ThirdPartyCapDescriptor::Builder initThirdPartyHosted(); inline void adoptThirdPartyHosted(::capnp::Orphan< ::capnp::rpc::ThirdPartyCapDescriptor>&& value); inline ::capnp::Orphan< ::capnp::rpc::ThirdPartyCapDescriptor> disownThirdPartyHosted(); inline ::uint8_t getAttachedFd(); inline void setAttachedFd( ::uint8_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class CapDescriptor::Pipeline { public: typedef CapDescriptor Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class PromisedAnswer::Reader { public: typedef PromisedAnswer Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId() const; inline bool hasTransform() const; inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Reader getTransform() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class PromisedAnswer::Builder { public: typedef PromisedAnswer Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline ::uint32_t getQuestionId(); inline void setQuestionId( ::uint32_t value); inline bool hasTransform(); inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Builder getTransform(); inline void setTransform( ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Reader value); inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Builder initTransform(unsigned int size); inline void adoptTransform(::capnp::Orphan< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>&& value); inline ::capnp::Orphan< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>> disownTransform(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class PromisedAnswer::Pipeline { public: typedef PromisedAnswer Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class PromisedAnswer::Op::Reader { public: typedef Op Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline Which which() const; inline bool isNoop() const; inline ::capnp::Void getNoop() const; inline bool isGetPointerField() const; inline ::uint16_t getGetPointerField() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class PromisedAnswer::Op::Builder { public: typedef Op Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline Which which(); inline bool isNoop(); inline ::capnp::Void getNoop(); inline void setNoop( ::capnp::Void value = ::capnp::VOID); inline bool isGetPointerField(); inline ::uint16_t getGetPointerField(); inline void setGetPointerField( ::uint16_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class PromisedAnswer::Op::Pipeline { public: typedef Op Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class ThirdPartyCapDescriptor::Reader { public: typedef ThirdPartyCapDescriptor Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasId() const; inline ::capnp::AnyPointer::Reader getId() const; inline ::uint32_t getVineId() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class ThirdPartyCapDescriptor::Builder { public: typedef ThirdPartyCapDescriptor Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasId(); inline ::capnp::AnyPointer::Builder getId(); inline ::capnp::AnyPointer::Builder initId(); inline ::uint32_t getVineId(); inline void setVineId( ::uint32_t value); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class ThirdPartyCapDescriptor::Pipeline { public: typedef ThirdPartyCapDescriptor Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE class Exception::Reader { public: typedef Exception Reads; Reader() = default; inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} inline ::capnp::MessageSize totalSize() const { return _reader.totalSize().asPublic(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); } #endif // !CAPNP_LITE inline bool hasReason() const; inline ::capnp::Text::Reader getReason() const; inline bool getObsoleteIsCallersFault() const; inline ::uint16_t getObsoleteDurability() const; inline ::capnp::rpc::Exception::Type getType() const; inline bool hasTrace() const; inline ::capnp::Text::Reader getTrace() const; private: ::capnp::_::StructReader _reader; template friend struct ::capnp::ToDynamic_; template friend struct ::capnp::_::PointerHelpers; template friend struct ::capnp::List; friend class ::capnp::MessageBuilder; friend class ::capnp::Orphanage; }; class Exception::Builder { public: typedef Exception Builds; Builder() = delete; // Deleted to discourage incorrect usage. // You can explicitly initialize to nullptr instead. inline Builder(decltype(nullptr)) {} inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} inline operator Reader() const { return Reader(_builder.asReader()); } inline Reader asReader() const { return *this; } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } #if !CAPNP_LITE inline ::kj::StringTree toString() const { return asReader().toString(); } #endif // !CAPNP_LITE inline bool hasReason(); inline ::capnp::Text::Builder getReason(); inline void setReason( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initReason(unsigned int size); inline void adoptReason(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownReason(); inline bool getObsoleteIsCallersFault(); inline void setObsoleteIsCallersFault(bool value); inline ::uint16_t getObsoleteDurability(); inline void setObsoleteDurability( ::uint16_t value); inline ::capnp::rpc::Exception::Type getType(); inline void setType( ::capnp::rpc::Exception::Type value); inline bool hasTrace(); inline ::capnp::Text::Builder getTrace(); inline void setTrace( ::capnp::Text::Reader value); inline ::capnp::Text::Builder initTrace(unsigned int size); inline void adoptTrace(::capnp::Orphan< ::capnp::Text>&& value); inline ::capnp::Orphan< ::capnp::Text> disownTrace(); private: ::capnp::_::StructBuilder _builder; template friend struct ::capnp::ToDynamic_; friend class ::capnp::Orphanage; template friend struct ::capnp::_::PointerHelpers; }; #if !CAPNP_LITE class Exception::Pipeline { public: typedef Exception Pipelines; inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) : _typeless(kj::mv(typeless)) {} private: ::capnp::AnyPointer::Pipeline _typeless; friend class ::capnp::PipelineHook; template friend struct ::capnp::ToDynamic_; }; #endif // !CAPNP_LITE // ======================================================================================= inline ::capnp::rpc::Message::Which Message::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Message::Which Message::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Message::Reader::isUnimplemented() const { return which() == Message::UNIMPLEMENTED; } inline bool Message::Builder::isUnimplemented() { return which() == Message::UNIMPLEMENTED; } inline bool Message::Reader::hasUnimplemented() const { if (which() != Message::UNIMPLEMENTED) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasUnimplemented() { if (which() != Message::UNIMPLEMENTED) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Message::Reader Message::Reader::getUnimplemented() const { KJ_IREQUIRE((which() == Message::UNIMPLEMENTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Message::Builder Message::Builder::getUnimplemented() { KJ_IREQUIRE((which() == Message::UNIMPLEMENTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setUnimplemented( ::capnp::rpc::Message::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::UNIMPLEMENTED); ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Message::Builder Message::Builder::initUnimplemented() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::UNIMPLEMENTED); return ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptUnimplemented( ::capnp::Orphan< ::capnp::rpc::Message>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::UNIMPLEMENTED); ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Message> Message::Builder::disownUnimplemented() { KJ_IREQUIRE((which() == Message::UNIMPLEMENTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Message>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isAbort() const { return which() == Message::ABORT; } inline bool Message::Builder::isAbort() { return which() == Message::ABORT; } inline bool Message::Reader::hasAbort() const { if (which() != Message::ABORT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasAbort() { if (which() != Message::ABORT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Exception::Reader Message::Reader::getAbort() const { KJ_IREQUIRE((which() == Message::ABORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Exception::Builder Message::Builder::getAbort() { KJ_IREQUIRE((which() == Message::ABORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setAbort( ::capnp::rpc::Exception::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ABORT); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Exception::Builder Message::Builder::initAbort() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ABORT); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptAbort( ::capnp::Orphan< ::capnp::rpc::Exception>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ABORT); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Exception> Message::Builder::disownAbort() { KJ_IREQUIRE((which() == Message::ABORT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isCall() const { return which() == Message::CALL; } inline bool Message::Builder::isCall() { return which() == Message::CALL; } inline bool Message::Reader::hasCall() const { if (which() != Message::CALL) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasCall() { if (which() != Message::CALL) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Call::Reader Message::Reader::getCall() const { KJ_IREQUIRE((which() == Message::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Call::Builder Message::Builder::getCall() { KJ_IREQUIRE((which() == Message::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setCall( ::capnp::rpc::Call::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::CALL); ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Call::Builder Message::Builder::initCall() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::CALL); return ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptCall( ::capnp::Orphan< ::capnp::rpc::Call>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::CALL); ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Call> Message::Builder::disownCall() { KJ_IREQUIRE((which() == Message::CALL), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Call>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isReturn() const { return which() == Message::RETURN; } inline bool Message::Builder::isReturn() { return which() == Message::RETURN; } inline bool Message::Reader::hasReturn() const { if (which() != Message::RETURN) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasReturn() { if (which() != Message::RETURN) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Return::Reader Message::Reader::getReturn() const { KJ_IREQUIRE((which() == Message::RETURN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Return::Builder Message::Builder::getReturn() { KJ_IREQUIRE((which() == Message::RETURN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setReturn( ::capnp::rpc::Return::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RETURN); ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Return::Builder Message::Builder::initReturn() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RETURN); return ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptReturn( ::capnp::Orphan< ::capnp::rpc::Return>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RETURN); ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Return> Message::Builder::disownReturn() { KJ_IREQUIRE((which() == Message::RETURN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Return>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isFinish() const { return which() == Message::FINISH; } inline bool Message::Builder::isFinish() { return which() == Message::FINISH; } inline bool Message::Reader::hasFinish() const { if (which() != Message::FINISH) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasFinish() { if (which() != Message::FINISH) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Finish::Reader Message::Reader::getFinish() const { KJ_IREQUIRE((which() == Message::FINISH), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Finish::Builder Message::Builder::getFinish() { KJ_IREQUIRE((which() == Message::FINISH), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setFinish( ::capnp::rpc::Finish::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::FINISH); ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Finish::Builder Message::Builder::initFinish() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::FINISH); return ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptFinish( ::capnp::Orphan< ::capnp::rpc::Finish>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::FINISH); ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Finish> Message::Builder::disownFinish() { KJ_IREQUIRE((which() == Message::FINISH), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Finish>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isResolve() const { return which() == Message::RESOLVE; } inline bool Message::Builder::isResolve() { return which() == Message::RESOLVE; } inline bool Message::Reader::hasResolve() const { if (which() != Message::RESOLVE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasResolve() { if (which() != Message::RESOLVE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Resolve::Reader Message::Reader::getResolve() const { KJ_IREQUIRE((which() == Message::RESOLVE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Resolve::Builder Message::Builder::getResolve() { KJ_IREQUIRE((which() == Message::RESOLVE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setResolve( ::capnp::rpc::Resolve::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RESOLVE); ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Resolve::Builder Message::Builder::initResolve() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RESOLVE); return ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptResolve( ::capnp::Orphan< ::capnp::rpc::Resolve>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RESOLVE); ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Resolve> Message::Builder::disownResolve() { KJ_IREQUIRE((which() == Message::RESOLVE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Resolve>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isRelease() const { return which() == Message::RELEASE; } inline bool Message::Builder::isRelease() { return which() == Message::RELEASE; } inline bool Message::Reader::hasRelease() const { if (which() != Message::RELEASE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasRelease() { if (which() != Message::RELEASE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Release::Reader Message::Reader::getRelease() const { KJ_IREQUIRE((which() == Message::RELEASE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Release::Builder Message::Builder::getRelease() { KJ_IREQUIRE((which() == Message::RELEASE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setRelease( ::capnp::rpc::Release::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RELEASE); ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Release::Builder Message::Builder::initRelease() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RELEASE); return ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptRelease( ::capnp::Orphan< ::capnp::rpc::Release>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::RELEASE); ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Release> Message::Builder::disownRelease() { KJ_IREQUIRE((which() == Message::RELEASE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Release>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isObsoleteSave() const { return which() == Message::OBSOLETE_SAVE; } inline bool Message::Builder::isObsoleteSave() { return which() == Message::OBSOLETE_SAVE; } inline bool Message::Reader::hasObsoleteSave() const { if (which() != Message::OBSOLETE_SAVE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasObsoleteSave() { if (which() != Message::OBSOLETE_SAVE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Message::Reader::getObsoleteSave() const { KJ_IREQUIRE((which() == Message::OBSOLETE_SAVE), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Message::Builder::getObsoleteSave() { KJ_IREQUIRE((which() == Message::OBSOLETE_SAVE), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Message::Builder::initObsoleteSave() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::OBSOLETE_SAVE); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Message::Reader::isBootstrap() const { return which() == Message::BOOTSTRAP; } inline bool Message::Builder::isBootstrap() { return which() == Message::BOOTSTRAP; } inline bool Message::Reader::hasBootstrap() const { if (which() != Message::BOOTSTRAP) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasBootstrap() { if (which() != Message::BOOTSTRAP) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Bootstrap::Reader Message::Reader::getBootstrap() const { KJ_IREQUIRE((which() == Message::BOOTSTRAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Bootstrap::Builder Message::Builder::getBootstrap() { KJ_IREQUIRE((which() == Message::BOOTSTRAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setBootstrap( ::capnp::rpc::Bootstrap::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::BOOTSTRAP); ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Bootstrap::Builder Message::Builder::initBootstrap() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::BOOTSTRAP); return ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptBootstrap( ::capnp::Orphan< ::capnp::rpc::Bootstrap>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::BOOTSTRAP); ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Bootstrap> Message::Builder::disownBootstrap() { KJ_IREQUIRE((which() == Message::BOOTSTRAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Bootstrap>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isObsoleteDelete() const { return which() == Message::OBSOLETE_DELETE; } inline bool Message::Builder::isObsoleteDelete() { return which() == Message::OBSOLETE_DELETE; } inline bool Message::Reader::hasObsoleteDelete() const { if (which() != Message::OBSOLETE_DELETE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasObsoleteDelete() { if (which() != Message::OBSOLETE_DELETE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Message::Reader::getObsoleteDelete() const { KJ_IREQUIRE((which() == Message::OBSOLETE_DELETE), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Message::Builder::getObsoleteDelete() { KJ_IREQUIRE((which() == Message::OBSOLETE_DELETE), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Message::Builder::initObsoleteDelete() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::OBSOLETE_DELETE); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Message::Reader::isProvide() const { return which() == Message::PROVIDE; } inline bool Message::Builder::isProvide() { return which() == Message::PROVIDE; } inline bool Message::Reader::hasProvide() const { if (which() != Message::PROVIDE) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasProvide() { if (which() != Message::PROVIDE) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Provide::Reader Message::Reader::getProvide() const { KJ_IREQUIRE((which() == Message::PROVIDE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Provide::Builder Message::Builder::getProvide() { KJ_IREQUIRE((which() == Message::PROVIDE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setProvide( ::capnp::rpc::Provide::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::PROVIDE); ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Provide::Builder Message::Builder::initProvide() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::PROVIDE); return ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptProvide( ::capnp::Orphan< ::capnp::rpc::Provide>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::PROVIDE); ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Provide> Message::Builder::disownProvide() { KJ_IREQUIRE((which() == Message::PROVIDE), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Provide>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isAccept() const { return which() == Message::ACCEPT; } inline bool Message::Builder::isAccept() { return which() == Message::ACCEPT; } inline bool Message::Reader::hasAccept() const { if (which() != Message::ACCEPT) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasAccept() { if (which() != Message::ACCEPT) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Accept::Reader Message::Reader::getAccept() const { KJ_IREQUIRE((which() == Message::ACCEPT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Accept::Builder Message::Builder::getAccept() { KJ_IREQUIRE((which() == Message::ACCEPT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setAccept( ::capnp::rpc::Accept::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ACCEPT); ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Accept::Builder Message::Builder::initAccept() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ACCEPT); return ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptAccept( ::capnp::Orphan< ::capnp::rpc::Accept>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::ACCEPT); ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Accept> Message::Builder::disownAccept() { KJ_IREQUIRE((which() == Message::ACCEPT), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Accept>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isJoin() const { return which() == Message::JOIN; } inline bool Message::Builder::isJoin() { return which() == Message::JOIN; } inline bool Message::Reader::hasJoin() const { if (which() != Message::JOIN) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasJoin() { if (which() != Message::JOIN) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Join::Reader Message::Reader::getJoin() const { KJ_IREQUIRE((which() == Message::JOIN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Join::Builder Message::Builder::getJoin() { KJ_IREQUIRE((which() == Message::JOIN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setJoin( ::capnp::rpc::Join::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::JOIN); ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Join::Builder Message::Builder::initJoin() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::JOIN); return ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptJoin( ::capnp::Orphan< ::capnp::rpc::Join>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::JOIN); ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Join> Message::Builder::disownJoin() { KJ_IREQUIRE((which() == Message::JOIN), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Join>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Message::Reader::isDisembargo() const { return which() == Message::DISEMBARGO; } inline bool Message::Builder::isDisembargo() { return which() == Message::DISEMBARGO; } inline bool Message::Reader::hasDisembargo() const { if (which() != Message::DISEMBARGO) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Message::Builder::hasDisembargo() { if (which() != Message::DISEMBARGO) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Disembargo::Reader Message::Reader::getDisembargo() const { KJ_IREQUIRE((which() == Message::DISEMBARGO), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Disembargo::Builder Message::Builder::getDisembargo() { KJ_IREQUIRE((which() == Message::DISEMBARGO), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::setDisembargo( ::capnp::rpc::Disembargo::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::DISEMBARGO); ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Disembargo::Builder Message::Builder::initDisembargo() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::DISEMBARGO); return ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Message::Builder::adoptDisembargo( ::capnp::Orphan< ::capnp::rpc::Disembargo>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, Message::DISEMBARGO); ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Disembargo> Message::Builder::disownDisembargo() { KJ_IREQUIRE((which() == Message::DISEMBARGO), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Disembargo>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Bootstrap::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Bootstrap::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Bootstrap::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Bootstrap::Reader::hasDeprecatedObjectId() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Bootstrap::Builder::hasDeprecatedObjectId() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Bootstrap::Reader::getDeprecatedObjectId() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Bootstrap::Builder::getDeprecatedObjectId() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Bootstrap::Builder::initDeprecatedObjectId() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::uint32_t Call::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Call::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Call::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Call::Reader::hasTarget() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Call::Builder::hasTarget() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::MessageTarget::Reader Call::Reader::getTarget() const { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::MessageTarget::Builder Call::Builder::getTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::rpc::MessageTarget::Pipeline Call::Pipeline::getTarget() { return ::capnp::rpc::MessageTarget::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Call::Builder::setTarget( ::capnp::rpc::MessageTarget::Reader value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::MessageTarget::Builder Call::Builder::initTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Call::Builder::adoptTarget( ::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> Call::Builder::disownTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint64_t Call::Reader::getInterfaceId() const { return _reader.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint64_t Call::Builder::getInterfaceId() { return _builder.getDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Call::Builder::setInterfaceId( ::uint64_t value) { _builder.setDataField< ::uint64_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Call::Reader::getMethodId() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint16_t Call::Builder::getMethodId() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Call::Builder::setMethodId( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Call::Reader::hasParams() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Call::Builder::hasParams() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Payload::Reader Call::Reader::getParams() const { return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Payload::Builder Call::Builder::getParams() { return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::rpc::Payload::Pipeline Call::Pipeline::getParams() { return ::capnp::rpc::Payload::Pipeline(_typeless.getPointerField(1)); } #endif // !CAPNP_LITE inline void Call::Builder::setParams( ::capnp::rpc::Payload::Reader value) { ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Payload::Builder Call::Builder::initParams() { return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Call::Builder::adoptParams( ::capnp::Orphan< ::capnp::rpc::Payload>&& value) { ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Payload> Call::Builder::disownParams() { return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline typename Call::SendResultsTo::Reader Call::Reader::getSendResultsTo() const { return typename Call::SendResultsTo::Reader(_reader); } inline typename Call::SendResultsTo::Builder Call::Builder::getSendResultsTo() { return typename Call::SendResultsTo::Builder(_builder); } #if !CAPNP_LITE inline typename Call::SendResultsTo::Pipeline Call::Pipeline::getSendResultsTo() { return typename Call::SendResultsTo::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Call::SendResultsTo::Builder Call::Builder::initSendResultsTo() { _builder.setDataField< ::uint16_t>(::capnp::bounded<3>() * ::capnp::ELEMENTS, 0); _builder.getPointerField(::capnp::bounded<2>() * ::capnp::POINTERS).clear(); return typename Call::SendResultsTo::Builder(_builder); } inline bool Call::Reader::getAllowThirdPartyTailCall() const { return _reader.getDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS); } inline bool Call::Builder::getAllowThirdPartyTailCall() { return _builder.getDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS); } inline void Call::Builder::setAllowThirdPartyTailCall(bool value) { _builder.setDataField( ::capnp::bounded<128>() * ::capnp::ELEMENTS, value); } inline bool Call::Reader::getNoPromisePipelining() const { return _reader.getDataField( ::capnp::bounded<129>() * ::capnp::ELEMENTS); } inline bool Call::Builder::getNoPromisePipelining() { return _builder.getDataField( ::capnp::bounded<129>() * ::capnp::ELEMENTS); } inline void Call::Builder::setNoPromisePipelining(bool value) { _builder.setDataField( ::capnp::bounded<129>() * ::capnp::ELEMENTS, value); } inline bool Call::Reader::getOnlyPromisePipeline() const { return _reader.getDataField( ::capnp::bounded<130>() * ::capnp::ELEMENTS); } inline bool Call::Builder::getOnlyPromisePipeline() { return _builder.getDataField( ::capnp::bounded<130>() * ::capnp::ELEMENTS); } inline void Call::Builder::setOnlyPromisePipeline(bool value) { _builder.setDataField( ::capnp::bounded<130>() * ::capnp::ELEMENTS, value); } inline ::capnp::rpc::Call::SendResultsTo::Which Call::SendResultsTo::Reader::which() const { return _reader.getDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Call::SendResultsTo::Which Call::SendResultsTo::Builder::which() { return _builder.getDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline bool Call::SendResultsTo::Reader::isCaller() const { return which() == Call::SendResultsTo::CALLER; } inline bool Call::SendResultsTo::Builder::isCaller() { return which() == Call::SendResultsTo::CALLER; } inline ::capnp::Void Call::SendResultsTo::Reader::getCaller() const { KJ_IREQUIRE((which() == Call::SendResultsTo::CALLER), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Call::SendResultsTo::Builder::getCaller() { KJ_IREQUIRE((which() == Call::SendResultsTo::CALLER), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Call::SendResultsTo::Builder::setCaller( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Call::SendResultsTo::CALLER); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Call::SendResultsTo::Reader::isYourself() const { return which() == Call::SendResultsTo::YOURSELF; } inline bool Call::SendResultsTo::Builder::isYourself() { return which() == Call::SendResultsTo::YOURSELF; } inline ::capnp::Void Call::SendResultsTo::Reader::getYourself() const { KJ_IREQUIRE((which() == Call::SendResultsTo::YOURSELF), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Call::SendResultsTo::Builder::getYourself() { KJ_IREQUIRE((which() == Call::SendResultsTo::YOURSELF), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Call::SendResultsTo::Builder::setYourself( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Call::SendResultsTo::YOURSELF); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Call::SendResultsTo::Reader::isThirdParty() const { return which() == Call::SendResultsTo::THIRD_PARTY; } inline bool Call::SendResultsTo::Builder::isThirdParty() { return which() == Call::SendResultsTo::THIRD_PARTY; } inline bool Call::SendResultsTo::Reader::hasThirdParty() const { if (which() != Call::SendResultsTo::THIRD_PARTY) return false; return !_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline bool Call::SendResultsTo::Builder::hasThirdParty() { if (which() != Call::SendResultsTo::THIRD_PARTY) return false; return !_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Call::SendResultsTo::Reader::getThirdParty() const { KJ_IREQUIRE((which() == Call::SendResultsTo::THIRD_PARTY), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Call::SendResultsTo::Builder::getThirdParty() { KJ_IREQUIRE((which() == Call::SendResultsTo::THIRD_PARTY), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Call::SendResultsTo::Builder::initThirdParty() { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Call::SendResultsTo::THIRD_PARTY); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<2>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::capnp::rpc::Return::Which Return::Reader::which() const { return _reader.getDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Return::Which Return::Builder::which() { return _builder.getDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS); } inline ::uint32_t Return::Reader::getAnswerId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Return::Builder::getAnswerId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Return::Builder::setAnswerId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Return::Reader::getReleaseParamCaps() const { return _reader.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, true); } inline bool Return::Builder::getReleaseParamCaps() { return _builder.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, true); } inline void Return::Builder::setReleaseParamCaps(bool value) { _builder.setDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, value, true); } inline bool Return::Reader::isResults() const { return which() == Return::RESULTS; } inline bool Return::Builder::isResults() { return which() == Return::RESULTS; } inline bool Return::Reader::hasResults() const { if (which() != Return::RESULTS) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Return::Builder::hasResults() { if (which() != Return::RESULTS) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Payload::Reader Return::Reader::getResults() const { KJ_IREQUIRE((which() == Return::RESULTS), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Payload::Builder Return::Builder::getResults() { KJ_IREQUIRE((which() == Return::RESULTS), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Return::Builder::setResults( ::capnp::rpc::Payload::Reader value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::RESULTS); ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Payload::Builder Return::Builder::initResults() { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::RESULTS); return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Return::Builder::adoptResults( ::capnp::Orphan< ::capnp::rpc::Payload>&& value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::RESULTS); ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Payload> Return::Builder::disownResults() { KJ_IREQUIRE((which() == Return::RESULTS), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Payload>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Return::Reader::isException() const { return which() == Return::EXCEPTION; } inline bool Return::Builder::isException() { return which() == Return::EXCEPTION; } inline bool Return::Reader::hasException() const { if (which() != Return::EXCEPTION) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Return::Builder::hasException() { if (which() != Return::EXCEPTION) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Exception::Reader Return::Reader::getException() const { KJ_IREQUIRE((which() == Return::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Exception::Builder Return::Builder::getException() { KJ_IREQUIRE((which() == Return::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Return::Builder::setException( ::capnp::rpc::Exception::Reader value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::EXCEPTION); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Exception::Builder Return::Builder::initException() { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::EXCEPTION); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Return::Builder::adoptException( ::capnp::Orphan< ::capnp::rpc::Exception>&& value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::EXCEPTION); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Exception> Return::Builder::disownException() { KJ_IREQUIRE((which() == Return::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Return::Reader::isCanceled() const { return which() == Return::CANCELED; } inline bool Return::Builder::isCanceled() { return which() == Return::CANCELED; } inline ::capnp::Void Return::Reader::getCanceled() const { KJ_IREQUIRE((which() == Return::CANCELED), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Return::Builder::getCanceled() { KJ_IREQUIRE((which() == Return::CANCELED), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Return::Builder::setCanceled( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::CANCELED); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Return::Reader::isResultsSentElsewhere() const { return which() == Return::RESULTS_SENT_ELSEWHERE; } inline bool Return::Builder::isResultsSentElsewhere() { return which() == Return::RESULTS_SENT_ELSEWHERE; } inline ::capnp::Void Return::Reader::getResultsSentElsewhere() const { KJ_IREQUIRE((which() == Return::RESULTS_SENT_ELSEWHERE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Return::Builder::getResultsSentElsewhere() { KJ_IREQUIRE((which() == Return::RESULTS_SENT_ELSEWHERE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Return::Builder::setResultsSentElsewhere( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::RESULTS_SENT_ELSEWHERE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Return::Reader::isTakeFromOtherQuestion() const { return which() == Return::TAKE_FROM_OTHER_QUESTION; } inline bool Return::Builder::isTakeFromOtherQuestion() { return which() == Return::TAKE_FROM_OTHER_QUESTION; } inline ::uint32_t Return::Reader::getTakeFromOtherQuestion() const { KJ_IREQUIRE((which() == Return::TAKE_FROM_OTHER_QUESTION), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Return::Builder::getTakeFromOtherQuestion() { KJ_IREQUIRE((which() == Return::TAKE_FROM_OTHER_QUESTION), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Return::Builder::setTakeFromOtherQuestion( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::TAKE_FROM_OTHER_QUESTION); _builder.setDataField< ::uint32_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Return::Reader::isAcceptFromThirdParty() const { return which() == Return::ACCEPT_FROM_THIRD_PARTY; } inline bool Return::Builder::isAcceptFromThirdParty() { return which() == Return::ACCEPT_FROM_THIRD_PARTY; } inline bool Return::Reader::hasAcceptFromThirdParty() const { if (which() != Return::ACCEPT_FROM_THIRD_PARTY) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Return::Builder::hasAcceptFromThirdParty() { if (which() != Return::ACCEPT_FROM_THIRD_PARTY) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Return::Reader::getAcceptFromThirdParty() const { KJ_IREQUIRE((which() == Return::ACCEPT_FROM_THIRD_PARTY), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Return::Builder::getAcceptFromThirdParty() { KJ_IREQUIRE((which() == Return::ACCEPT_FROM_THIRD_PARTY), "Must check which() before get()ing a union member."); return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Return::Builder::initAcceptFromThirdParty() { _builder.setDataField( ::capnp::bounded<3>() * ::capnp::ELEMENTS, Return::ACCEPT_FROM_THIRD_PARTY); auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Return::Reader::getNoFinishNeeded() const { return _reader.getDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS); } inline bool Return::Builder::getNoFinishNeeded() { return _builder.getDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS); } inline void Return::Builder::setNoFinishNeeded(bool value) { _builder.setDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Finish::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Finish::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Finish::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Finish::Reader::getReleaseResultCaps() const { return _reader.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, true); } inline bool Finish::Builder::getReleaseResultCaps() { return _builder.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, true); } inline void Finish::Builder::setReleaseResultCaps(bool value) { _builder.setDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, value, true); } inline bool Finish::Reader::getRequireEarlyCancellationWorkaround() const { return _reader.getDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS, true); } inline bool Finish::Builder::getRequireEarlyCancellationWorkaround() { return _builder.getDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS, true); } inline void Finish::Builder::setRequireEarlyCancellationWorkaround(bool value) { _builder.setDataField( ::capnp::bounded<33>() * ::capnp::ELEMENTS, value, true); } inline ::capnp::rpc::Resolve::Which Resolve::Reader::which() const { return _reader.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Resolve::Which Resolve::Builder::which() { return _builder.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::uint32_t Resolve::Reader::getPromiseId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Resolve::Builder::getPromiseId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Resolve::Builder::setPromiseId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Resolve::Reader::isCap() const { return which() == Resolve::CAP; } inline bool Resolve::Builder::isCap() { return which() == Resolve::CAP; } inline bool Resolve::Reader::hasCap() const { if (which() != Resolve::CAP) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Resolve::Builder::hasCap() { if (which() != Resolve::CAP) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::CapDescriptor::Reader Resolve::Reader::getCap() const { KJ_IREQUIRE((which() == Resolve::CAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::CapDescriptor::Builder Resolve::Builder::getCap() { KJ_IREQUIRE((which() == Resolve::CAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Resolve::Builder::setCap( ::capnp::rpc::CapDescriptor::Reader value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::CAP); ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::CapDescriptor::Builder Resolve::Builder::initCap() { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::CAP); return ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Resolve::Builder::adoptCap( ::capnp::Orphan< ::capnp::rpc::CapDescriptor>&& value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::CAP); ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::CapDescriptor> Resolve::Builder::disownCap() { KJ_IREQUIRE((which() == Resolve::CAP), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::CapDescriptor>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Resolve::Reader::isException() const { return which() == Resolve::EXCEPTION; } inline bool Resolve::Builder::isException() { return which() == Resolve::EXCEPTION; } inline bool Resolve::Reader::hasException() const { if (which() != Resolve::EXCEPTION) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Resolve::Builder::hasException() { if (which() != Resolve::EXCEPTION) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::Exception::Reader Resolve::Reader::getException() const { KJ_IREQUIRE((which() == Resolve::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::Exception::Builder Resolve::Builder::getException() { KJ_IREQUIRE((which() == Resolve::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Resolve::Builder::setException( ::capnp::rpc::Exception::Reader value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::EXCEPTION); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::Exception::Builder Resolve::Builder::initException() { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::EXCEPTION); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Resolve::Builder::adoptException( ::capnp::Orphan< ::capnp::rpc::Exception>&& value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Resolve::EXCEPTION); ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::Exception> Resolve::Builder::disownException() { KJ_IREQUIRE((which() == Resolve::EXCEPTION), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::Exception>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint32_t Release::Reader::getId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Release::Builder::getId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Release::Builder::setId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Release::Reader::getReferenceCount() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t Release::Builder::getReferenceCount() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Release::Builder::setReferenceCount( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool Disembargo::Reader::hasTarget() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Disembargo::Builder::hasTarget() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::MessageTarget::Reader Disembargo::Reader::getTarget() const { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::MessageTarget::Builder Disembargo::Builder::getTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::rpc::MessageTarget::Pipeline Disembargo::Pipeline::getTarget() { return ::capnp::rpc::MessageTarget::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Disembargo::Builder::setTarget( ::capnp::rpc::MessageTarget::Reader value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::MessageTarget::Builder Disembargo::Builder::initTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Disembargo::Builder::adoptTarget( ::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> Disembargo::Builder::disownTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline typename Disembargo::Context::Reader Disembargo::Reader::getContext() const { return typename Disembargo::Context::Reader(_reader); } inline typename Disembargo::Context::Builder Disembargo::Builder::getContext() { return typename Disembargo::Context::Builder(_builder); } #if !CAPNP_LITE inline typename Disembargo::Context::Pipeline Disembargo::Pipeline::getContext() { return typename Disembargo::Context::Pipeline(_typeless.noop()); } #endif // !CAPNP_LITE inline typename Disembargo::Context::Builder Disembargo::Builder::initContext() { _builder.setDataField< ::uint32_t>(::capnp::bounded<0>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint16_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0); return typename Disembargo::Context::Builder(_builder); } inline ::capnp::rpc::Disembargo::Context::Which Disembargo::Context::Reader::which() const { return _reader.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Disembargo::Context::Which Disembargo::Context::Builder::which() { return _builder.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline bool Disembargo::Context::Reader::isSenderLoopback() const { return which() == Disembargo::Context::SENDER_LOOPBACK; } inline bool Disembargo::Context::Builder::isSenderLoopback() { return which() == Disembargo::Context::SENDER_LOOPBACK; } inline ::uint32_t Disembargo::Context::Reader::getSenderLoopback() const { KJ_IREQUIRE((which() == Disembargo::Context::SENDER_LOOPBACK), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Disembargo::Context::Builder::getSenderLoopback() { KJ_IREQUIRE((which() == Disembargo::Context::SENDER_LOOPBACK), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Disembargo::Context::Builder::setSenderLoopback( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Disembargo::Context::SENDER_LOOPBACK); _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Disembargo::Context::Reader::isReceiverLoopback() const { return which() == Disembargo::Context::RECEIVER_LOOPBACK; } inline bool Disembargo::Context::Builder::isReceiverLoopback() { return which() == Disembargo::Context::RECEIVER_LOOPBACK; } inline ::uint32_t Disembargo::Context::Reader::getReceiverLoopback() const { KJ_IREQUIRE((which() == Disembargo::Context::RECEIVER_LOOPBACK), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Disembargo::Context::Builder::getReceiverLoopback() { KJ_IREQUIRE((which() == Disembargo::Context::RECEIVER_LOOPBACK), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Disembargo::Context::Builder::setReceiverLoopback( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Disembargo::Context::RECEIVER_LOOPBACK); _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Disembargo::Context::Reader::isAccept() const { return which() == Disembargo::Context::ACCEPT; } inline bool Disembargo::Context::Builder::isAccept() { return which() == Disembargo::Context::ACCEPT; } inline ::capnp::Void Disembargo::Context::Reader::getAccept() const { KJ_IREQUIRE((which() == Disembargo::Context::ACCEPT), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void Disembargo::Context::Builder::getAccept() { KJ_IREQUIRE((which() == Disembargo::Context::ACCEPT), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Disembargo::Context::Builder::setAccept( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Disembargo::Context::ACCEPT); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Disembargo::Context::Reader::isProvide() const { return which() == Disembargo::Context::PROVIDE; } inline bool Disembargo::Context::Builder::isProvide() { return which() == Disembargo::Context::PROVIDE; } inline ::uint32_t Disembargo::Context::Reader::getProvide() const { KJ_IREQUIRE((which() == Disembargo::Context::PROVIDE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Disembargo::Context::Builder::getProvide() { KJ_IREQUIRE((which() == Disembargo::Context::PROVIDE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Disembargo::Context::Builder::setProvide( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, Disembargo::Context::PROVIDE); _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Provide::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Provide::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Provide::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Provide::Reader::hasTarget() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Provide::Builder::hasTarget() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::MessageTarget::Reader Provide::Reader::getTarget() const { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::MessageTarget::Builder Provide::Builder::getTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::rpc::MessageTarget::Pipeline Provide::Pipeline::getTarget() { return ::capnp::rpc::MessageTarget::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Provide::Builder::setTarget( ::capnp::rpc::MessageTarget::Reader value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::MessageTarget::Builder Provide::Builder::initTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Provide::Builder::adoptTarget( ::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> Provide::Builder::disownTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Provide::Reader::hasRecipient() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Provide::Builder::hasRecipient() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Provide::Reader::getRecipient() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Provide::Builder::getRecipient() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Provide::Builder::initRecipient() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::uint32_t Accept::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Accept::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Accept::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Accept::Reader::hasProvision() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Accept::Builder::hasProvision() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Accept::Reader::getProvision() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Accept::Builder::getProvision() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Accept::Builder::initProvision() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Accept::Reader::getEmbargo() const { return _reader.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS); } inline bool Accept::Builder::getEmbargo() { return _builder.getDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS); } inline void Accept::Builder::setEmbargo(bool value) { _builder.setDataField( ::capnp::bounded<32>() * ::capnp::ELEMENTS, value); } inline ::uint32_t Join::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t Join::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Join::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Join::Reader::hasTarget() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Join::Builder::hasTarget() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::MessageTarget::Reader Join::Reader::getTarget() const { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::MessageTarget::Builder Join::Builder::getTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } #if !CAPNP_LITE inline ::capnp::rpc::MessageTarget::Pipeline Join::Pipeline::getTarget() { return ::capnp::rpc::MessageTarget::Pipeline(_typeless.getPointerField(0)); } #endif // !CAPNP_LITE inline void Join::Builder::setTarget( ::capnp::rpc::MessageTarget::Reader value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::MessageTarget::Builder Join::Builder::initTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Join::Builder::adoptTarget( ::capnp::Orphan< ::capnp::rpc::MessageTarget>&& value) { ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::MessageTarget> Join::Builder::disownTarget() { return ::capnp::_::PointerHelpers< ::capnp::rpc::MessageTarget>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Join::Reader::hasKeyPart() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Join::Builder::hasKeyPart() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Join::Reader::getKeyPart() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Join::Builder::getKeyPart() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Join::Builder::initKeyPart() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::capnp::rpc::MessageTarget::Which MessageTarget::Reader::which() const { return _reader.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::MessageTarget::Which MessageTarget::Builder::which() { return _builder.getDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline bool MessageTarget::Reader::isImportedCap() const { return which() == MessageTarget::IMPORTED_CAP; } inline bool MessageTarget::Builder::isImportedCap() { return which() == MessageTarget::IMPORTED_CAP; } inline ::uint32_t MessageTarget::Reader::getImportedCap() const { KJ_IREQUIRE((which() == MessageTarget::IMPORTED_CAP), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t MessageTarget::Builder::getImportedCap() { KJ_IREQUIRE((which() == MessageTarget::IMPORTED_CAP), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void MessageTarget::Builder::setImportedCap( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, MessageTarget::IMPORTED_CAP); _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool MessageTarget::Reader::isPromisedAnswer() const { return which() == MessageTarget::PROMISED_ANSWER; } inline bool MessageTarget::Builder::isPromisedAnswer() { return which() == MessageTarget::PROMISED_ANSWER; } inline bool MessageTarget::Reader::hasPromisedAnswer() const { if (which() != MessageTarget::PROMISED_ANSWER) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool MessageTarget::Builder::hasPromisedAnswer() { if (which() != MessageTarget::PROMISED_ANSWER) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::PromisedAnswer::Reader MessageTarget::Reader::getPromisedAnswer() const { KJ_IREQUIRE((which() == MessageTarget::PROMISED_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::PromisedAnswer::Builder MessageTarget::Builder::getPromisedAnswer() { KJ_IREQUIRE((which() == MessageTarget::PROMISED_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void MessageTarget::Builder::setPromisedAnswer( ::capnp::rpc::PromisedAnswer::Reader value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, MessageTarget::PROMISED_ANSWER); ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::PromisedAnswer::Builder MessageTarget::Builder::initPromisedAnswer() { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, MessageTarget::PROMISED_ANSWER); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void MessageTarget::Builder::adoptPromisedAnswer( ::capnp::Orphan< ::capnp::rpc::PromisedAnswer>&& value) { _builder.setDataField( ::capnp::bounded<2>() * ::capnp::ELEMENTS, MessageTarget::PROMISED_ANSWER); ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::PromisedAnswer> MessageTarget::Builder::disownPromisedAnswer() { KJ_IREQUIRE((which() == MessageTarget::PROMISED_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Payload::Reader::hasContent() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Payload::Builder::hasContent() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader Payload::Reader::getContent() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Payload::Builder::getContent() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder Payload::Builder::initContent() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline bool Payload::Reader::hasCapTable() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Payload::Builder::hasCapTable() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Reader Payload::Reader::getCapTable() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Builder Payload::Builder::getCapTable() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Payload::Builder::setCapTable( ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>::Builder Payload::Builder::initCapTable(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Payload::Builder::adoptCapTable( ::capnp::Orphan< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>> Payload::Builder::disownCapTable() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::CapDescriptor, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::rpc::CapDescriptor::Which CapDescriptor::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::CapDescriptor::Which CapDescriptor::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool CapDescriptor::Reader::isNone() const { return which() == CapDescriptor::NONE; } inline bool CapDescriptor::Builder::isNone() { return which() == CapDescriptor::NONE; } inline ::capnp::Void CapDescriptor::Reader::getNone() const { KJ_IREQUIRE((which() == CapDescriptor::NONE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void CapDescriptor::Builder::getNone() { KJ_IREQUIRE((which() == CapDescriptor::NONE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void CapDescriptor::Builder::setNone( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::NONE); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool CapDescriptor::Reader::isSenderHosted() const { return which() == CapDescriptor::SENDER_HOSTED; } inline bool CapDescriptor::Builder::isSenderHosted() { return which() == CapDescriptor::SENDER_HOSTED; } inline ::uint32_t CapDescriptor::Reader::getSenderHosted() const { KJ_IREQUIRE((which() == CapDescriptor::SENDER_HOSTED), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t CapDescriptor::Builder::getSenderHosted() { KJ_IREQUIRE((which() == CapDescriptor::SENDER_HOSTED), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CapDescriptor::Builder::setSenderHosted( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::SENDER_HOSTED); _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool CapDescriptor::Reader::isSenderPromise() const { return which() == CapDescriptor::SENDER_PROMISE; } inline bool CapDescriptor::Builder::isSenderPromise() { return which() == CapDescriptor::SENDER_PROMISE; } inline ::uint32_t CapDescriptor::Reader::getSenderPromise() const { KJ_IREQUIRE((which() == CapDescriptor::SENDER_PROMISE), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t CapDescriptor::Builder::getSenderPromise() { KJ_IREQUIRE((which() == CapDescriptor::SENDER_PROMISE), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CapDescriptor::Builder::setSenderPromise( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::SENDER_PROMISE); _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool CapDescriptor::Reader::isReceiverHosted() const { return which() == CapDescriptor::RECEIVER_HOSTED; } inline bool CapDescriptor::Builder::isReceiverHosted() { return which() == CapDescriptor::RECEIVER_HOSTED; } inline ::uint32_t CapDescriptor::Reader::getReceiverHosted() const { KJ_IREQUIRE((which() == CapDescriptor::RECEIVER_HOSTED), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint32_t CapDescriptor::Builder::getReceiverHosted() { KJ_IREQUIRE((which() == CapDescriptor::RECEIVER_HOSTED), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void CapDescriptor::Builder::setReceiverHosted( ::uint32_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::RECEIVER_HOSTED); _builder.setDataField< ::uint32_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool CapDescriptor::Reader::isReceiverAnswer() const { return which() == CapDescriptor::RECEIVER_ANSWER; } inline bool CapDescriptor::Builder::isReceiverAnswer() { return which() == CapDescriptor::RECEIVER_ANSWER; } inline bool CapDescriptor::Reader::hasReceiverAnswer() const { if (which() != CapDescriptor::RECEIVER_ANSWER) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CapDescriptor::Builder::hasReceiverAnswer() { if (which() != CapDescriptor::RECEIVER_ANSWER) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::PromisedAnswer::Reader CapDescriptor::Reader::getReceiverAnswer() const { KJ_IREQUIRE((which() == CapDescriptor::RECEIVER_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::PromisedAnswer::Builder CapDescriptor::Builder::getReceiverAnswer() { KJ_IREQUIRE((which() == CapDescriptor::RECEIVER_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CapDescriptor::Builder::setReceiverAnswer( ::capnp::rpc::PromisedAnswer::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::RECEIVER_ANSWER); ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::PromisedAnswer::Builder CapDescriptor::Builder::initReceiverAnswer() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::RECEIVER_ANSWER); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CapDescriptor::Builder::adoptReceiverAnswer( ::capnp::Orphan< ::capnp::rpc::PromisedAnswer>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::RECEIVER_ANSWER); ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::PromisedAnswer> CapDescriptor::Builder::disownReceiverAnswer() { KJ_IREQUIRE((which() == CapDescriptor::RECEIVER_ANSWER), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::PromisedAnswer>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool CapDescriptor::Reader::isThirdPartyHosted() const { return which() == CapDescriptor::THIRD_PARTY_HOSTED; } inline bool CapDescriptor::Builder::isThirdPartyHosted() { return which() == CapDescriptor::THIRD_PARTY_HOSTED; } inline bool CapDescriptor::Reader::hasThirdPartyHosted() const { if (which() != CapDescriptor::THIRD_PARTY_HOSTED) return false; return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool CapDescriptor::Builder::hasThirdPartyHosted() { if (which() != CapDescriptor::THIRD_PARTY_HOSTED) return false; return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::rpc::ThirdPartyCapDescriptor::Reader CapDescriptor::Reader::getThirdPartyHosted() const { KJ_IREQUIRE((which() == CapDescriptor::THIRD_PARTY_HOSTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::ThirdPartyCapDescriptor::Builder CapDescriptor::Builder::getThirdPartyHosted() { KJ_IREQUIRE((which() == CapDescriptor::THIRD_PARTY_HOSTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CapDescriptor::Builder::setThirdPartyHosted( ::capnp::rpc::ThirdPartyCapDescriptor::Reader value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::THIRD_PARTY_HOSTED); ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::rpc::ThirdPartyCapDescriptor::Builder CapDescriptor::Builder::initThirdPartyHosted() { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::THIRD_PARTY_HOSTED); return ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void CapDescriptor::Builder::adoptThirdPartyHosted( ::capnp::Orphan< ::capnp::rpc::ThirdPartyCapDescriptor>&& value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, CapDescriptor::THIRD_PARTY_HOSTED); ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::rpc::ThirdPartyCapDescriptor> CapDescriptor::Builder::disownThirdPartyHosted() { KJ_IREQUIRE((which() == CapDescriptor::THIRD_PARTY_HOSTED), "Must check which() before get()ing a union member."); return ::capnp::_::PointerHelpers< ::capnp::rpc::ThirdPartyCapDescriptor>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::uint8_t CapDescriptor::Reader::getAttachedFd() const { return _reader.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, 255u); } inline ::uint8_t CapDescriptor::Builder::getAttachedFd() { return _builder.getDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, 255u); } inline void CapDescriptor::Builder::setAttachedFd( ::uint8_t value) { _builder.setDataField< ::uint8_t>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value, 255u); } inline ::uint32_t PromisedAnswer::Reader::getQuestionId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t PromisedAnswer::Builder::getQuestionId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void PromisedAnswer::Builder::setQuestionId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool PromisedAnswer::Reader::hasTransform() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool PromisedAnswer::Builder::hasTransform() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Reader PromisedAnswer::Reader::getTransform() const { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Builder PromisedAnswer::Builder::getTransform() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void PromisedAnswer::Builder::setTransform( ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Reader value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>::Builder PromisedAnswer::Builder::initTransform(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void PromisedAnswer::Builder::adoptTransform( ::capnp::Orphan< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>&& value) { ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>> PromisedAnswer::Builder::disownTransform() { return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::rpc::PromisedAnswer::Op, ::capnp::Kind::STRUCT>>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::rpc::PromisedAnswer::Op::Which PromisedAnswer::Op::Reader::which() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::PromisedAnswer::Op::Which PromisedAnswer::Op::Builder::which() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool PromisedAnswer::Op::Reader::isNoop() const { return which() == PromisedAnswer::Op::NOOP; } inline bool PromisedAnswer::Op::Builder::isNoop() { return which() == PromisedAnswer::Op::NOOP; } inline ::capnp::Void PromisedAnswer::Op::Reader::getNoop() const { KJ_IREQUIRE((which() == PromisedAnswer::Op::NOOP), "Must check which() before get()ing a union member."); return _reader.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::capnp::Void PromisedAnswer::Op::Builder::getNoop() { KJ_IREQUIRE((which() == PromisedAnswer::Op::NOOP), "Must check which() before get()ing a union member."); return _builder.getDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void PromisedAnswer::Op::Builder::setNoop( ::capnp::Void value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, PromisedAnswer::Op::NOOP); _builder.setDataField< ::capnp::Void>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool PromisedAnswer::Op::Reader::isGetPointerField() const { return which() == PromisedAnswer::Op::GET_POINTER_FIELD; } inline bool PromisedAnswer::Op::Builder::isGetPointerField() { return which() == PromisedAnswer::Op::GET_POINTER_FIELD; } inline ::uint16_t PromisedAnswer::Op::Reader::getGetPointerField() const { KJ_IREQUIRE((which() == PromisedAnswer::Op::GET_POINTER_FIELD), "Must check which() before get()ing a union member."); return _reader.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint16_t PromisedAnswer::Op::Builder::getGetPointerField() { KJ_IREQUIRE((which() == PromisedAnswer::Op::GET_POINTER_FIELD), "Must check which() before get()ing a union member."); return _builder.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void PromisedAnswer::Op::Builder::setGetPointerField( ::uint16_t value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, PromisedAnswer::Op::GET_POINTER_FIELD); _builder.setDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline bool ThirdPartyCapDescriptor::Reader::hasId() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool ThirdPartyCapDescriptor::Builder::hasId() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::AnyPointer::Reader ThirdPartyCapDescriptor::Reader::getId() const { return ::capnp::AnyPointer::Reader(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder ThirdPartyCapDescriptor::Builder::getId() { return ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::AnyPointer::Builder ThirdPartyCapDescriptor::Builder::initId() { auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); result.clear(); return result; } inline ::uint32_t ThirdPartyCapDescriptor::Reader::getVineId() const { return _reader.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline ::uint32_t ThirdPartyCapDescriptor::Builder::getVineId() { return _builder.getDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void ThirdPartyCapDescriptor::Builder::setVineId( ::uint32_t value) { _builder.setDataField< ::uint32_t>( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline bool Exception::Reader::hasReason() const { return !_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline bool Exception::Builder::hasReason() { return !_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Exception::Reader::getReason() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Exception::Builder::getReason() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline void Exception::Builder::setReason( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Exception::Builder::initReason(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), size); } inline void Exception::Builder::adoptReason( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Exception::Builder::disownReason() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<0>() * ::capnp::POINTERS)); } inline bool Exception::Reader::getObsoleteIsCallersFault() const { return _reader.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline bool Exception::Builder::getObsoleteIsCallersFault() { return _builder.getDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS); } inline void Exception::Builder::setObsoleteIsCallersFault(bool value) { _builder.setDataField( ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); } inline ::uint16_t Exception::Reader::getObsoleteDurability() const { return _reader.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline ::uint16_t Exception::Builder::getObsoleteDurability() { return _builder.getDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS); } inline void Exception::Builder::setObsoleteDurability( ::uint16_t value) { _builder.setDataField< ::uint16_t>( ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); } inline ::capnp::rpc::Exception::Type Exception::Reader::getType() const { return _reader.getDataField< ::capnp::rpc::Exception::Type>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline ::capnp::rpc::Exception::Type Exception::Builder::getType() { return _builder.getDataField< ::capnp::rpc::Exception::Type>( ::capnp::bounded<2>() * ::capnp::ELEMENTS); } inline void Exception::Builder::setType( ::capnp::rpc::Exception::Type value) { _builder.setDataField< ::capnp::rpc::Exception::Type>( ::capnp::bounded<2>() * ::capnp::ELEMENTS, value); } inline bool Exception::Reader::hasTrace() const { return !_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline bool Exception::Builder::hasTrace() { return !_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); } inline ::capnp::Text::Reader Exception::Reader::getTrace() const { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline ::capnp::Text::Builder Exception::Builder::getTrace() { return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } inline void Exception::Builder::setTrace( ::capnp::Text::Reader value) { ::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), value); } inline ::capnp::Text::Builder Exception::Builder::initTrace(unsigned int size) { return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), size); } inline void Exception::Builder::adoptTrace( ::capnp::Orphan< ::capnp::Text>&& value) { ::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); } inline ::capnp::Orphan< ::capnp::Text> Exception::Builder::disownTrace() { return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField( ::capnp::bounded<1>() * ::capnp::POINTERS)); } } // namespace } // namespace CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/persistent.capnp.c++0000644000175000017500000002163214527152321022432 0ustar00kentonkenton00000000000000// Generated by Cap'n Proto compiler, DO NOT EDIT // source: persistent.capnp #include "persistent.capnp.h" namespace capnp { namespace schemas { static const ::capnp::_::AlignedData<54> b_c8cb212fcd9f5691 = { { 0, 0, 0, 0, 5, 0, 6, 0, 145, 86, 159, 205, 47, 33, 203, 200, 23, 0, 0, 0, 3, 0, 0, 0, 215, 238, 63, 152, 54, 8, 99, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 71, 0, 0, 0, 145, 0, 0, 0, 7, 0, 0, 0, 145, 0, 0, 0, 23, 0, 0, 0, 99, 97, 112, 110, 112, 47, 112, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 99, 97, 112, 110, 112, 58, 80, 101, 114, 115, 105, 115, 116, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 165, 115, 48, 24, 89, 186, 111, 247, 9, 0, 0, 0, 90, 0, 0, 0, 191, 239, 64, 140, 193, 72, 104, 183, 9, 0, 0, 0, 98, 0, 0, 0, 83, 97, 118, 101, 80, 97, 114, 97, 109, 115, 0, 0, 0, 0, 0, 0, 83, 97, 118, 101, 82, 101, 115, 117, 108, 116, 115, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 115, 48, 24, 89, 186, 111, 247, 191, 239, 64, 140, 193, 72, 104, 183, 17, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 1, 0, 28, 0, 0, 0, 0, 0, 1, 0, 45, 0, 0, 0, 7, 0, 0, 0, 115, 97, 118, 101, 0, 0, 0, 0, 1, 0, 0, 0, 31, 0, 0, 0, 4, 0, 0, 0, 2, 0, 1, 0, 145, 86, 159, 205, 47, 33, 203, 200, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 31, 0, 0, 0, 4, 0, 0, 0, 2, 0, 1, 0, 145, 86, 159, 205, 47, 33, 203, 200, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 8, 0, 0, 0, 0, 0, 1, 0, 5, 0, 0, 0, 82, 0, 0, 0, 9, 0, 0, 0, 50, 0, 0, 0, 83, 116, 117, 114, 100, 121, 82, 101, 102, 0, 0, 0, 0, 0, 0, 0, 79, 119, 110, 101, 114, 0, 0, 0, } }; ::capnp::word const* const bp_c8cb212fcd9f5691 = b_c8cb212fcd9f5691.words; #if !CAPNP_LITE static const ::capnp::_::RawSchema* const d_c8cb212fcd9f5691[] = { &s_b76848c18c40efbf, &s_f76fba59183073a5, }; static const uint16_t m_c8cb212fcd9f5691[] = {0}; KJ_CONSTEXPR(const) ::capnp::_::RawBrandedSchema::Dependency bd_c8cb212fcd9f5691[] = { { 33554432, ::capnp::Persistent< ::capnp::AnyPointer, ::capnp::AnyPointer>::SaveParams::_capnpPrivate::brand() }, { 50331648, ::capnp::Persistent< ::capnp::AnyPointer, ::capnp::AnyPointer>::SaveResults::_capnpPrivate::brand() }, }; const ::capnp::_::RawSchema s_c8cb212fcd9f5691 = { 0xc8cb212fcd9f5691, b_c8cb212fcd9f5691.words, 54, d_c8cb212fcd9f5691, m_c8cb212fcd9f5691, 2, 1, nullptr, nullptr, nullptr, { &s_c8cb212fcd9f5691, nullptr, bd_c8cb212fcd9f5691, 0, sizeof(bd_c8cb212fcd9f5691) / sizeof(bd_c8cb212fcd9f5691[0]), nullptr }, false }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<35> b_f76fba59183073a5 = { { 0, 0, 0, 0, 5, 0, 6, 0, 165, 115, 48, 24, 89, 186, 111, 247, 34, 0, 0, 0, 1, 0, 0, 0, 145, 86, 159, 205, 47, 33, 203, 200, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 21, 0, 0, 0, 106, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 112, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 99, 97, 112, 110, 112, 58, 80, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 83, 97, 118, 101, 80, 97, 114, 97, 109, 115, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 3, 0, 1, 0, 20, 0, 0, 0, 2, 0, 1, 0, 115, 101, 97, 108, 70, 111, 114, 0, 18, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 145, 86, 159, 205, 47, 33, 203, 200, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f76fba59183073a5 = b_f76fba59183073a5.words; #if !CAPNP_LITE static const uint16_t m_f76fba59183073a5[] = {0}; static const uint16_t i_f76fba59183073a5[] = {0}; const ::capnp::_::RawSchema s_f76fba59183073a5 = { 0xf76fba59183073a5, b_f76fba59183073a5.words, 35, nullptr, m_f76fba59183073a5, 0, 1, i_f76fba59183073a5, nullptr, nullptr, { &s_f76fba59183073a5, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<36> b_b76848c18c40efbf = { { 0, 0, 0, 0, 5, 0, 6, 0, 191, 239, 64, 140, 193, 72, 104, 183, 34, 0, 0, 0, 1, 0, 0, 0, 145, 86, 159, 205, 47, 33, 203, 200, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 21, 0, 0, 0, 114, 1, 0, 0, 41, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 112, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 99, 97, 112, 110, 112, 58, 80, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 83, 97, 118, 101, 82, 101, 115, 117, 108, 116, 115, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 1, 0, 24, 0, 0, 0, 2, 0, 1, 0, 115, 116, 117, 114, 100, 121, 82, 101, 102, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 86, 159, 205, 47, 33, 203, 200, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_b76848c18c40efbf = b_b76848c18c40efbf.words; #if !CAPNP_LITE static const uint16_t m_b76848c18c40efbf[] = {0}; static const uint16_t i_b76848c18c40efbf[] = {0}; const ::capnp::_::RawSchema s_b76848c18c40efbf = { 0xb76848c18c40efbf, b_b76848c18c40efbf.words, 36, nullptr, m_b76848c18c40efbf, 0, 1, i_b76848c18c40efbf, nullptr, nullptr, { &s_b76848c18c40efbf, nullptr, nullptr, 0, 0, nullptr }, true }; #endif // !CAPNP_LITE static const ::capnp::_::AlignedData<22> b_f622595091cafb67 = { { 0, 0, 0, 0, 5, 0, 6, 0, 103, 251, 202, 145, 80, 89, 34, 246, 23, 0, 0, 0, 5, 0, 32, 1, 215, 238, 63, 152, 54, 8, 99, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 18, 1, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 112, 110, 112, 47, 112, 101, 114, 115, 105, 115, 116, 101, 110, 116, 46, 99, 97, 112, 110, 112, 58, 112, 101, 114, 115, 105, 115, 116, 101, 110, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }; ::capnp::word const* const bp_f622595091cafb67 = b_f622595091cafb67.words; #if !CAPNP_LITE const ::capnp::_::RawSchema s_f622595091cafb67 = { 0xf622595091cafb67, b_f622595091cafb67.words, 22, nullptr, nullptr, 0, 0, nullptr, nullptr, nullptr, { &s_f622595091cafb67, nullptr, nullptr, 0, 0, nullptr }, false }; #endif // !CAPNP_LITE } // namespace schemas } // namespace capnp capnproto-c++-1.1.0/src/capnp/pretty-print.h0000644000175000017500000000360314527152321021470 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "dynamic.h" #include CAPNP_BEGIN_HEADER namespace capnp { kj::StringTree prettyPrint(DynamicStruct::Reader value); kj::StringTree prettyPrint(DynamicStruct::Builder value); kj::StringTree prettyPrint(DynamicList::Reader value); kj::StringTree prettyPrint(DynamicList::Builder value); // Print the given Cap'n Proto struct or list with nice indentation. Note that you can pass any // struct or list reader or builder type to this method, since they can be implicitly converted // to one of the dynamic types. // // If you don't want indentation, just use the value's KJ stringifier (e.g. pass it to kj::str(), // any of the KJ debug macros, etc.). } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/rpc-twoparty.capnp0000644000175000017500000002264014527152321022336 0ustar00kentonkenton00000000000000# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. @0xa184c7885cdaf2a1; # This file defines the "network-specific parameters" in rpc.capnp to support a network consisting # of two vats. Each of these vats may in fact be in communication with other vats, but any # capabilities they forward must be proxied. Thus, to each end of the connection, all capabilities # received from the other end appear to live in a single vat. # # Two notable use cases for this model include: # - Regular client-server communications, where a remote client machine (perhaps living on an end # user's personal device) connects to a server. The server may be part of a cluster, and may # call on other servers in the cluster to help service the user's request. It may even obtain # capabilities from these other servers which it passes on to the user. To simplify network # common traversal problems (e.g. if the user is behind a firewall), it is probably desirable to # multiplex all communications between the server cluster and the client over the original # connection rather than form new ones. This connection should use the two-party protocol, as # the client has no interest in knowing about additional servers. # - Applications running in a sandbox. A supervisor process may execute a confined application # such that all of the confined app's communications with the outside world must pass through # the supervisor. In this case, the connection between the confined app and the supervisor might # as well use the two-party protocol, because the confined app is intentionally prevented from # talking to any other vat anyway. Any external resources will be proxied through the supervisor, # and so to the contained app will appear as if they were hosted by the supervisor itself. # # Since there are only two vats in this network, there is never a need for three-way introductions, # so level 3 is free. Moreover, because it is never necessary to form new connections, the # two-party protocol can be used easily anywhere where a two-way byte stream exists, without regard # to where that byte stream goes or how it was initiated. This makes the two-party runtime library # highly reusable. # # Joins (level 4) _could_ be needed in cases where one or both vats are participating in other # networks that use joins. For instance, if Alice and Bob are speaking through the two-party # protocol, and Bob is also participating on another network, Bob may send Alice two or more # proxied capabilities which, unbeknownst to Bob at the time, are in fact pointing at the same # remote object. Alice may then request to join these capabilities, at which point Bob will have # to forward the join to the other network. Note, however, that if Alice is _not_ participating on # any other network, then Alice will never need to _receive_ a Join, because Alice would always # know when two locally-hosted capabilities are the same and would never export a redundant alias # to Bob. So, Alice can respond to all incoming joins with an error, and only needs to implement # outgoing joins if she herself desires to use this feature. Also, outgoing joins are relatively # easy to implement in this scenario. # # What all this means is that a level 4 implementation of the confined network is barely more # complicated than a level 2 implementation. However, such an implementation allows the "client" # or "confined" app to access the server's/supervisor's network with equal functionality to any # native participant. In other words, an application which implements only the two-party protocol # can be paired with a proxy app in order to participate in any network. # # So, when implementing Cap'n Proto in a new language, it makes sense to implement only the # two-party protocol initially, and then pair applications with an appropriate proxy written in # C++, rather than implement other parameterizations of the RPC protocol directly. using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("capnp::rpc::twoparty"); # Note: SturdyRef is not specified here. It is up to the application to define semantics of # SturdyRefs if desired. enum Side { server @0; # The object lives on the "server" or "supervisor" end of the connection. Only the # server/supervisor knows how to interpret the ref; to the client, it is opaque. # # Note that containers intending to implement strong confinement should rewrite SturdyRefs # received from the external network before passing them on to the confined app. The confined # app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps # maliciously leak), but instead receives only a thing that it can pass back to the container # later to restore the ref. See: # http://www.erights.org/elib/capability/dist-confine.html client @1; # The object lives on the "client" or "confined app" end of the connection. Only the client # knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not # actually know how to persist capabilities at all, so use of this is unusual. } struct VatId { side @0 :Side; } struct ProvisionId { # Only used for joins, since three-way introductions never happen on a two-party network. joinId @0 :UInt32; # The ID from `JoinKeyPart`. } struct RecipientId {} # Never used, because there are only two parties. struct ThirdPartyCapId {} # Never used, because there is no third party. struct JoinKeyPart { # Joins in the two-party case are simplified by a few observations. # # First, on a two-party network, a Join only ever makes sense if the receiving end is also # connected to other networks. A vat which is not connected to any other network can safely # reject all joins. # # Second, since a two-party connection bisects the network -- there can be no other connections # between the networks at either end of the connection -- if one part of a join crosses the # connection, then _all_ parts must cross it. Therefore, a vat which is receiving a Join request # off some other network which needs to be forwarded across the two-party connection can # collect all the parts on its end and only forward them across the two-party connection when all # have been received. # # For example, imagine that Alice and Bob are vats connected over a two-party connection, and # each is also connected to other networks. At some point, Alice receives one part of a Join # request off her network. The request is addressed to a capability that Alice received from # Bob and is proxying to her other network. Alice goes ahead and responds to the Join part as # if she hosted the capability locally (this is important so that if not all the Join parts end # up at Alice, the original sender can detect the failed Join without hanging). As other parts # trickle in, Alice verifies that each part is addressed to a capability from Bob and continues # to respond to each one. Once the complete set of join parts is received, Alice checks if they # were all for the exact same capability. If so, she doesn't need to send anything to Bob at # all. Otherwise, she collects the set of capabilities (from Bob) to which the join parts were # addressed and essentially initiates a _new_ Join request on those capabilities to Bob. Alice # does not forward the Join parts she received herself, but essentially forwards the Join as a # whole. # # On Bob's end, since he knows that Alice will always send all parts of a Join together, he # simply waits until he's received them all, then performs a join on the respective capabilities # as if it had been requested locally. joinId @0 :UInt32; # A number identifying this join, chosen by the sender. May be reused once `Finish` messages are # sent corresponding to all of the `Join` messages. partCount @1 :UInt16; # The number of capabilities to be joined. partNum @2 :UInt16; # Which part this request targets -- a number in the range [0, partCount). } struct JoinResult { joinId @0 :UInt32; # Matches `JoinKeyPart`. succeeded @1 :Bool; # All JoinResults in the set will have the same value for `succeeded`. The receiver actually # implements the join by waiting for all the `JoinKeyParts` and then performing its own join on # them, then going back and answering all the join requests afterwards. cap @2 :Capability; # One of the JoinResults will have a non-null `cap` which is the joined capability. } capnproto-c++-1.1.0/src/capnp/serialize-async.h0000644000175000017500000003266614712011043022113 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include #include #include "message.h" CAPNP_BEGIN_HEADER namespace capnp { struct MessageReaderAndFds { kj::Own reader; kj::ArrayPtr fds; }; struct MessageAndFds { kj::ArrayPtr> segments; kj::ArrayPtr fds; }; class MessageStream { // Interface over which messages can be sent and received; virtualizes // the functionality above. public: virtual kj::Promise> tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) = 0; // Read a message that may also have file descriptors attached, e.g. from a Unix socket with // SCM_RIGHTS. Returns null on EOF. // // `scratchSpace`, if provided, must remain valid until the returned MessageReader is destroyed. kj::Promise>> tryReadMessage( ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Equivalent to the above with fdSpace = nullptr. kj::Promise readMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); kj::Promise> readMessage( ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); // Like tryReadMessage, but throws an exception on EOF. virtual kj::Promise writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) KJ_WARN_UNUSED_RESULT = 0; kj::Promise writeMessage( kj::ArrayPtr fds, MessageBuilder& builder) KJ_WARN_UNUSED_RESULT; // Write a message with FDs attached, e.g. to a Unix socket with SCM_RIGHTS. // The parameters must remain valid until the returned promise resolves. kj::Promise writeMessage( kj::ArrayPtr> segments) KJ_WARN_UNUSED_RESULT; kj::Promise writeMessage(MessageBuilder& builder) KJ_WARN_UNUSED_RESULT; // Equivalent to the above with fds = nullptr. kj::Promise writeMessages( kj::ArrayPtr messages) KJ_WARN_UNUSED_RESULT; virtual kj::Promise writeMessages( kj::ArrayPtr>> messages) KJ_WARN_UNUSED_RESULT = 0; kj::Promise writeMessages(kj::ArrayPtr builders) KJ_WARN_UNUSED_RESULT; // Similar to the above, but for writing multiple messages at a time in a batch. virtual kj::Maybe getSendBufferSize() = 0; // Get the size of the underlying send buffer, if applicable. The RPC // system uses this as a hint for flow control purposes; see: // // https://capnproto.org/news/2020-04-23-capnproto-0.8.html#multi-stream-flow-control // // ...for a more thorough explanation of how this is used. Implementations // may return nullptr if they do not have access to this information, or if // the underlying transport does not use a congestion window. virtual kj::Promise end() = 0; // Cleanly shut down just the write end of the transport, while keeping the read end open. }; class AsyncIoMessageStream final: public MessageStream { // A MessageStream that wraps an AsyncIoStream. public: explicit AsyncIoMessageStream(kj::AsyncIoStream& stream); // Implements MessageStream kj::Promise> tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) override; kj::Promise writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) override; kj::Promise writeMessages( kj::ArrayPtr>> messages) override; kj::Maybe getSendBufferSize() override; kj::Promise end() override; // Make sure the overridden virtual methods don't hide the non-virtual methods. using MessageStream::tryReadMessage; using MessageStream::writeMessage; private: kj::AsyncIoStream& stream; }; class AsyncCapabilityMessageStream final: public MessageStream { // A MessageStream that wraps an AsyncCapabilityStream. public: explicit AsyncCapabilityMessageStream(kj::AsyncCapabilityStream& stream); // Implements MessageStream kj::Promise> tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) override; kj::Promise writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) override; kj::Promise writeMessages( kj::ArrayPtr>> messages) override; kj::Maybe getSendBufferSize() override; kj::Promise end() override; // Make sure the overridden virtual methods don't hide the non-virtual methods. using MessageStream::tryReadMessage; using MessageStream::writeMessage; private: kj::AsyncCapabilityStream& stream; }; class BufferedMessageStream final: public MessageStream { // A MessageStream that reads into a buffer in the hopes of receiving multiple messages in a // single system call. Compared to the other implementations, this implementation is expected // to be faster when reading from an OS stream (but probably not when reading from an in-memory // async pipe). It has the down sides of using more memory (for the buffer) and requiring extra // copies. public: using IsShortLivedCallback = kj::Function; // Callback function which decides whether a message will be "short-lived", meaning that it is // guaranteed to be dropped before the next message is read. The stream uses this as an // optimization to decide whether it can return a MessageReader pointing into the buffer, which // will be reused for future reads. For long-lived messages, the stream must copy the content // into a separate buffer. explicit BufferedMessageStream( kj::AsyncIoStream& stream, IsShortLivedCallback isShortLivedCallback, size_t bufferSizeInWords = 8192); explicit BufferedMessageStream( kj::AsyncCapabilityStream& stream, IsShortLivedCallback isShortLivedCallback, size_t bufferSizeInWords = 8192); // Implements MessageStream kj::Promise> tryReadMessage( kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr) override; kj::Promise writeMessage( kj::ArrayPtr fds, kj::ArrayPtr> segments) override; kj::Promise writeMessages( kj::ArrayPtr>> messages) override; kj::Maybe getSendBufferSize() override; kj::Promise end() override; // Make sure the overridden virtual methods don't hide the non-virtual methods. using MessageStream::tryReadMessage; using MessageStream::writeMessage; private: kj::AsyncIoStream& stream; kj::Maybe capStream; IsShortLivedCallback isShortLivedCallback; kj::Array buffer; word* beginData; // Pointer to location in `buffer` where the next message starts. This is always on a word // boundray since messages are always a whole number of words. kj::byte* beginAvailable; // Pointer to the location in `buffer` where unused buffer space begins, i.e. immediately after // the last byte read. kj::Vector leftoverFds; // FDs which were accidentally read too early. These are always connected to the last message // in the buffer, since the OS would not have allowed us to read past that point. bool hasOutstandingShortLivedMessage = false; kj::Promise> tryReadMessageImpl( kj::ArrayPtr fdSpace, size_t fdsSoFar, ReaderOptions options, kj::ArrayPtr scratchSpace); kj::Promise> readEntireMessage( kj::ArrayPtr prefix, size_t expectedSizeInWords, kj::ArrayPtr fdSpace, size_t fdsSoFar, ReaderOptions options); // Given a message prefix and expected size of the whole message, read the entire message into // a single array and return it. kj::Promise tryReadWithFds( void* buffer, size_t minBytes, size_t maxBytes, kj::AutoCloseFd* fdBuffer, size_t maxFds); // Executes AsyncCapabilityStream::tryReadWithFds() on the underlying stream, or falls back to // AsyncIoStream::tryRead() if it's not a capability stream. class MessageReaderImpl; }; // ----------------------------------------------------------------------------- // Stand-alone functions for reading & writing messages on AsyncInput/AsyncOutputStreams. // // In general, foo(stream, ...) is equivalent to // AsyncIoMessageStream(stream).foo(...), whenever the latter would type check. // // The first argument must remain valid until the returned promise resolves // (or is canceled). kj::Promise> readMessage( kj::AsyncInputStream& input, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); kj::Promise>> tryReadMessage( kj::AsyncInputStream& input, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); kj::Promise writeMessage(kj::AsyncOutputStream& output, kj::ArrayPtr> segments) KJ_WARN_UNUSED_RESULT; kj::Promise writeMessage(kj::AsyncOutputStream& output, MessageBuilder& builder) KJ_WARN_UNUSED_RESULT; // ----------------------------------------------------------------------------- // Stand-alone versions that support FD passing. // // For each of these, `foo(stream, ...)` is equivalent to // `AsyncCapabilityMessageStream(stream).foo(...)`. kj::Promise readMessage( kj::AsyncCapabilityStream& input, kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); kj::Promise> tryReadMessage( kj::AsyncCapabilityStream& input, kj::ArrayPtr fdSpace, ReaderOptions options = ReaderOptions(), kj::ArrayPtr scratchSpace = nullptr); kj::Promise writeMessage(kj::AsyncCapabilityStream& output, kj::ArrayPtr fds, kj::ArrayPtr> segments) KJ_WARN_UNUSED_RESULT; kj::Promise writeMessage(kj::AsyncCapabilityStream& output, kj::ArrayPtr fds, MessageBuilder& builder) KJ_WARN_UNUSED_RESULT; // ----------------------------------------------------------------------------- // Stand-alone functions for writing multiple messages at once on AsyncOutputStreams. kj::Promise writeMessages(kj::AsyncOutputStream& output, kj::ArrayPtr>> messages) KJ_WARN_UNUSED_RESULT; kj::Promise writeMessages( kj::AsyncOutputStream& output, kj::ArrayPtr builders) KJ_WARN_UNUSED_RESULT; // ======================================================================================= // inline implementation details inline kj::Promise writeMessage(kj::AsyncOutputStream& output, MessageBuilder& builder) { return writeMessage(output, builder.getSegmentsForOutput()); } inline kj::Promise writeMessage( kj::AsyncCapabilityStream& output, kj::ArrayPtr fds, MessageBuilder& builder) { return writeMessage(output, fds, builder.getSegmentsForOutput()); } inline kj::Promise MessageStream::writeMessage(kj::ArrayPtr> segments) { return writeMessage(nullptr, segments); } inline kj::Promise MessageStream::writeMessage(MessageBuilder& builder) { return writeMessage(builder.getSegmentsForOutput()); } inline kj::Promise MessageStream::writeMessage( kj::ArrayPtr fds, MessageBuilder& builder) { return writeMessage(fds, builder.getSegmentsForOutput()); } } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/capnp/canonicalize-test.c++0000644000175000017500000003423014712011043022533 0ustar00kentonkenton00000000000000// Copyright (c) 2016 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "message.h" #include "any.h" #include #include #include "test-util.h" namespace capnp { namespace _ { // private using test::TestLists; namespace { KJ_TEST("canonicalize yields canonical message") { MallocMessageBuilder builder; auto root = builder.initRoot(); initTestMessage(root); auto canonicalWords = canonicalize(root.asReader()); // Throws an exception on canonicalization failure. kj::ArrayPtr canonicalSegments[1] = {canonicalWords.asPtr()}; capnp::SegmentArrayMessageReader canonicalReader(kj::arrayPtr(canonicalSegments, 1)); KJ_ASSERT(AnyStruct::Reader(root.asReader()) == AnyStruct::Reader(canonicalReader.getRoot())); } KJ_TEST("canonicalize succeeds on empty struct") { MallocMessageBuilder builder; auto root = builder.initRoot(); canonicalize(root.asReader()); // Throws an exception on canoncalization failure. } KJ_TEST("data word with only its most significant bit set does not get truncated") { AlignedData<3> segment = {{ // Struct pointer, body immediately follows, two data words 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // First data word 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // Second data word, all zero except most significant bit 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 3)}; SegmentArrayMessageReader messageReader(kj::arrayPtr(segments, 1)); KJ_ASSERT(messageReader.isCanonical()); auto canonicalWords = canonicalize(messageReader.getRoot()); // At one point this failed because an off-by-one bug in canonicalization // caused the second word of the data section to be truncated. ASSERT_EQ(canonicalWords.asBytes(), kj::arrayPtr(segment.bytes, 3 * 8)); } KJ_TEST("INLINE_COMPOSITE data word with only its most significant bit set does not get truncated") { AlignedData<5> segment = {{ // Struct pointer, body immediately follows, one pointer 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // List pointer, no offset, inline composite, two words long 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, // Tag word, list has one element with two data words and no pointers 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // First data word 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, // Second data word, all zero except most significant bit 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 5)}; SegmentArrayMessageReader messageReader(kj::arrayPtr(segments, 1)); KJ_ASSERT(messageReader.isCanonical()); auto canonicalWords = canonicalize(messageReader.getRoot()); // At one point this failed because an off-by-one bug in canonicalization // caused the second word of the data section to be truncated. ASSERT_EQ(canonicalWords.asBytes(), kj::arrayPtr(segment.bytes, 5 * 8)); } KJ_TEST("canonical non-null empty struct field") { AlignedData<4> nonNullEmptyStruct = {{ // Struct pointer, body immediately follows, two pointer fields, no data. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, // First pointer field, struct, offset of 1, data size 1, no pointers. 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Non-null pointer to empty struct. 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, // Body of struct filled with non-zero data. 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(nonNullEmptyStruct.words, 4)}; SegmentArrayMessageReader messageReader(kj::arrayPtr(segments, 1)); KJ_ASSERT(messageReader.isCanonical()); } KJ_TEST("for pointers to empty structs, preorder is not canonical") { AlignedData<4> nonNullEmptyStruct = {{ // Struct pointer, body immediately follows, two pointer fields, no data. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, // First pointer field, struct, offset of 1, data size 1, no pointers. 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Non-null pointer to empty struct. Offset puts it in "preorder". Would need to have // an offset of -1 to be canonical. 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Body of struct filled with non-zero data. 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(nonNullEmptyStruct.words, 4)}; SegmentArrayMessageReader messageReader(kj::arrayPtr(segments, 1)); KJ_ASSERT(!messageReader.isCanonical()); } KJ_TEST("isCanonical requires pointer preorder") { AlignedData<5> misorderedSegment = {{ //Struct pointer, data immediately follows, two pointer fields, no data 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, //Pointer field 1, pointing to the last entry, data size 1, no pointer 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //Pointer field 2, pointing to the next entry, data size 2, no pointer 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //Data for field 2 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, //Data for field 1 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(misorderedSegment.words, 5)}; SegmentArrayMessageReader outOfOrder(kj::arrayPtr(segments, 1)); KJ_ASSERT(!outOfOrder.isCanonical()); } KJ_TEST("isCanonical requires dense packing") { AlignedData<3> gapSegment = {{ //Struct pointer, data after a gap 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //The gap 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Data for field 1 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(gapSegment.words, 3)}; SegmentArrayMessageReader gap(kj::arrayPtr(segments, 1)); KJ_ASSERT(!gap.isCanonical()); } KJ_TEST("isCanonical rejects multi-segment messages") { AlignedData<1> farPtr = {{ //Far pointer to next segment 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, }}; AlignedData<2> farTarget = {{ //Struct pointer (needed to make the far pointer legal) 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //Dummy data 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, }}; kj::ArrayPtr segments[2] = { kj::arrayPtr(farPtr.words, 1), kj::arrayPtr(farTarget.words, 2) }; SegmentArrayMessageReader multiSegmentMessage(kj::arrayPtr(segments, 2)); KJ_ASSERT(!multiSegmentMessage.isCanonical()); } KJ_TEST("isCanonical rejects zero segment messages") { SegmentArrayMessageReader zero(kj::arrayPtr((kj::ArrayPtr*)NULL, 0)); KJ_ASSERT(!zero.isCanonical()); } KJ_TEST("isCanonical requires truncation of 0-valued struct fields") { AlignedData<2> nonTruncatedSegment = {{ //Struct pointer, data immediately follows 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, //Default data value, should have been truncated 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments[1] = { kj::arrayPtr(nonTruncatedSegment.words, 3) }; SegmentArrayMessageReader nonTruncated(kj::arrayPtr(segments, 1)); KJ_ASSERT(!nonTruncated.isCanonical()); } KJ_TEST("isCanonical rejects unused trailing words") { AlignedData<3> segment = {{ // Struct pointer, data in next word 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Data section of struct 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Trailing zero word 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 3)}; SegmentArrayMessageReader message(kj::arrayPtr(segments, 1)); KJ_ASSERT(!message.isCanonical()); } KJ_TEST("isCanonical accepts empty inline composite list of zero-sized structs") { AlignedData<3> segment = {{ // Struct pointer, pointer in next word 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // List pointer, inline composite, zero words long 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // Tag word 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 3)}; SegmentArrayMessageReader message(kj::arrayPtr(segments, 1)); KJ_ASSERT(message.isCanonical()); } KJ_TEST("isCanonical rejects inline composite list with inaccurate word-length") { AlignedData<6> segment = {{ // Struct pointer, no offset, pointer section has two entries 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, // List pointer, offset of one, inline composite, two words long // (The list only needs to be one word long to hold its actual elements; // therefore this message is not canonical.) 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, // Struct pointer, offset two, data section has one word 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Tag word, struct, one element, one word data section 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // Data section of struct element of list 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Data section of struct field in top-level struct 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 6)}; SegmentArrayMessageReader message(kj::arrayPtr(segments, 1)); KJ_ASSERT(!message.isCanonical()); } KJ_TEST("upgraded lists can be canonicalized") { AlignedData<7> upgradedList = {{ //Struct pointer, data immediately follows, 4 pointer fields, no data 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, //Three words of default pointers to get to the int16 list 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //List pointer, 3 int16s. 0x01, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, //First two elements 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, //Last element 0x07, 0x08, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00 }}; kj::ArrayPtr segments[1] = { kj::arrayPtr(upgradedList.words, 7) }; SegmentArrayMessageReader upgraded(kj::arrayPtr(segments, 1)); auto root = upgraded.getRoot(); canonicalize(root); } KJ_TEST("isCanonical requires truncation of 0-valued struct fields in all list members") { AlignedData<6> nonTruncatedList = {{ //List pointer, composite, 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, //Struct tag word, 2 structs, 2 data words per struct 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, //Data word non-null 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, //Null trailing word 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Data word non-null 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, //Null trailing word 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; kj::ArrayPtr segments[1] = { kj::arrayPtr(nonTruncatedList.words, 6) }; SegmentArrayMessageReader nonTruncated(kj::arrayPtr(segments, 1)); KJ_ASSERT(!nonTruncated.isCanonical()); } KJ_TEST("primitive list with nonzero padding") { AlignedData<3> segment = {{ // Struct, one pointer field. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // List of three byte-sized elements. 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, // Fourth byte is non-zero! 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 3)}; SegmentArrayMessageReader message(kj::arrayPtr(segments, 1)); KJ_ASSERT(!message.isCanonical()); auto canonicalWords = canonicalize(message.getRoot()); AlignedData<3> canonicalSegment = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, }}; ASSERT_EQ(canonicalWords.asBytes(), kj::arrayPtr(canonicalSegment.bytes, 3 * 8)); } KJ_TEST("bit list with nonzero padding") { AlignedData<3> segment = {{ // Struct, one pointer field. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // List of eleven bit-sized elements. 0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, // Twelfth bit is non-zero! 0xee, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; kj::ArrayPtr segments[1] = {kj::arrayPtr(segment.words, 3)}; SegmentArrayMessageReader message(kj::arrayPtr(segments, 1)); KJ_ASSERT(!message.isCanonical()); auto canonicalWords = canonicalize(message.getRoot()); AlignedData<3> canonicalSegment = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0xee, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }}; ASSERT_EQ(canonicalWords.asBytes(), kj::arrayPtr(canonicalSegment.bytes, 3 * 8)); } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize.c++0000644000175000017500000002567414712011043021122 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "serialize.h" #include "layout.h" #include #include #ifdef _WIN32 #include #include #endif namespace capnp { FlatArrayMessageReader::FlatArrayMessageReader( kj::ArrayPtr array, ReaderOptions options) : MessageReader(options), end(array.end()) { if (array.size() < 1) { // Assume empty message. return; } const _::WireValue* table = reinterpret_cast*>(array.begin()); uint segmentCount = table[0].get() + 1; size_t offset = segmentCount / 2u + 1u; KJ_REQUIRE(array.size() >= offset, "Message ends prematurely in segment table.") { return; } { uint segmentSize = table[1].get(); KJ_REQUIRE(array.size() >= offset + segmentSize, "Message ends prematurely in first segment.") { return; } segment0 = array.slice(offset, offset + segmentSize); offset += segmentSize; } if (segmentCount > 1) { moreSegments = kj::heapArray>(segmentCount - 1); for (uint i = 1; i < segmentCount; i++) { uint segmentSize = table[i + 1].get(); KJ_REQUIRE(array.size() >= offset + segmentSize, "Message ends prematurely.") { moreSegments = nullptr; return; } moreSegments[i - 1] = array.slice(offset, offset + segmentSize); offset += segmentSize; } } end = array.begin() + offset; } size_t expectedSizeInWordsFromPrefix(kj::ArrayPtr array) { if (array.size() < 1) { // All messages are at least one word. return 1; } const _::WireValue* table = reinterpret_cast*>(array.begin()); uint segmentCount = table[0].get() + 1; size_t offset = segmentCount / 2u + 1u; // If the array is too small to contain the full segment table, truncate segmentCount to just // what is available. segmentCount = kj::min(segmentCount, array.size() * 2 - 1u); size_t totalSize = offset; for (uint i = 0; i < segmentCount; i++) { totalSize += table[i + 1].get(); } return totalSize; } kj::ArrayPtr FlatArrayMessageReader::getSegment(uint id) { if (id == 0) { return segment0; } else if (id <= moreSegments.size()) { return moreSegments[id - 1]; } else { return nullptr; } } kj::ArrayPtr initMessageBuilderFromFlatArrayCopy( kj::ArrayPtr array, MessageBuilder& target, ReaderOptions options) { FlatArrayMessageReader reader(array, options); target.setRoot(reader.getRoot()); return kj::arrayPtr(reader.getEnd(), array.end()); } kj::Array messageToFlatArray(kj::ArrayPtr> segments) { kj::Array result = kj::heapArray(computeSerializedSizeInWords(segments)); _::WireValue* table = reinterpret_cast<_::WireValue*>(result.begin()); // We write the segment count - 1 because this makes the first word zero for single-segment // messages, improving compression. We don't bother doing this with segment sizes because // one-word segments are rare anyway. table[0].set(segments.size() - 1); for (uint i = 0; i < segments.size(); i++) { table[i + 1].set(segments[i].size()); } if (segments.size() % 2 == 0) { // Set padding byte. table[segments.size() + 1].set(0); } word* dst = result.begin() + segments.size() / 2 + 1; for (auto& segment: segments) { memcpy(dst, segment.begin(), segment.size() * sizeof(word)); dst += segment.size(); } KJ_DASSERT(dst == result.end(), "Buffer overrun/underrun bug in code above."); return kj::mv(result); } size_t computeSerializedSizeInWords(kj::ArrayPtr> segments) { KJ_REQUIRE(segments.size() > 0, "Tried to serialize uninitialized message."); size_t totalSize = segments.size() / 2 + 1; for (auto& segment: segments) { totalSize += segment.size(); } return totalSize; } // ======================================================================================= InputStreamMessageReader::InputStreamMessageReader( kj::InputStream& inputStream, ReaderOptions options, kj::ArrayPtr scratchSpace) : MessageReader(options), inputStream(inputStream), readPos(nullptr) { _::WireValue firstWord[2]; inputStream.read(firstWord, sizeof(firstWord)); uint segmentCount = firstWord[0].get() + 1; uint segment0Size = segmentCount == 0 ? 0 : firstWord[1].get(); size_t totalWords = segment0Size; // Reject messages with too many segments for security reasons. KJ_REQUIRE(segmentCount < 512, "Message has too many segments.") { segmentCount = 1; segment0Size = 1; break; } // Read sizes for all segments except the first. Include padding if necessary. KJ_STACK_ARRAY(_::WireValue, moreSizes, segmentCount & ~1, 16, 64); if (segmentCount > 1) { inputStream.read(moreSizes.begin(), moreSizes.size() * sizeof(moreSizes[0])); for (uint i = 0; i < segmentCount - 1; i++) { totalWords += moreSizes[i].get(); } } // Don't accept a message which the receiver couldn't possibly traverse without hitting the // traversal limit. Without this check, a malicious client could transmit a very large segment // size to make the receiver allocate excessive space and possibly crash. KJ_REQUIRE(totalWords <= options.traversalLimitInWords, "Message is too large. To increase the limit on the receiving end, see " "capnp::ReaderOptions.") { segmentCount = 1; segment0Size = kj::min(segment0Size, options.traversalLimitInWords); totalWords = segment0Size; break; } if (scratchSpace.size() < totalWords) { // TODO(perf): Consider allocating each segment as a separate chunk to reduce memory // fragmentation. ownedSpace = kj::heapArray(totalWords); scratchSpace = ownedSpace; } segment0 = scratchSpace.slice(0, segment0Size); if (segmentCount > 1) { moreSegments = kj::heapArray>(segmentCount - 1); size_t offset = segment0Size; for (uint i = 0; i < segmentCount - 1; i++) { uint segmentSize = moreSizes[i].get(); moreSegments[i] = scratchSpace.slice(offset, offset + segmentSize); offset += segmentSize; } } if (segmentCount == 1) { inputStream.read(scratchSpace.begin(), totalWords * sizeof(word)); } else if (segmentCount > 1) { readPos = scratchSpace.asBytes().begin(); readPos += inputStream.read(readPos, segment0Size * sizeof(word), totalWords * sizeof(word)); } } InputStreamMessageReader::~InputStreamMessageReader() noexcept(false) { if (readPos != nullptr) { unwindDetector.catchExceptionsIfUnwinding([&]() { // Note that lazy reads only happen when we have multiple segments, so moreSegments.back() is // valid. const byte* allEnd = reinterpret_cast(moreSegments.back().end()); inputStream.skip(allEnd - readPos); }); } } kj::ArrayPtr InputStreamMessageReader::getSegment(uint id) { if (id > moreSegments.size()) { return nullptr; } kj::ArrayPtr segment = id == 0 ? segment0 : moreSegments[id - 1]; if (readPos != nullptr) { // May need to lazily read more data. const byte* segmentEnd = reinterpret_cast(segment.end()); if (readPos < segmentEnd) { // Note that lazy reads only happen when we have multiple segments, so moreSegments.back() is // valid. const byte* allEnd = reinterpret_cast(moreSegments.back().end()); readPos += inputStream.read(readPos, segmentEnd - readPos, allEnd - readPos); } } return segment; } void readMessageCopy(kj::InputStream& input, MessageBuilder& target, ReaderOptions options, kj::ArrayPtr scratchSpace) { InputStreamMessageReader message(input, options, scratchSpace); target.setRoot(message.getRoot()); } // ------------------------------------------------------------------- void writeMessage(kj::OutputStream& output, kj::ArrayPtr> segments) { KJ_REQUIRE(segments.size() > 0, "Tried to serialize uninitialized message."); KJ_STACK_ARRAY(_::WireValue, table, (segments.size() + 2) & ~size_t(1), 16, 64); // We write the segment count - 1 because this makes the first word zero for single-segment // messages, improving compression. We don't bother doing this with segment sizes because // one-word segments are rare anyway. table[0].set(segments.size() - 1); for (uint i = 0; i < segments.size(); i++) { table[i + 1].set(segments[i].size()); } if (segments.size() % 2 == 0) { // Set padding byte. table[segments.size() + 1].set(0); } KJ_STACK_ARRAY(kj::ArrayPtr, pieces, segments.size() + 1, 4, 32); pieces[0] = table.asBytes(); for (uint i = 0; i < segments.size(); i++) { pieces[i + 1] = segments[i].asBytes(); } output.write(pieces); } // ======================================================================================= StreamFdMessageReader::~StreamFdMessageReader() noexcept(false) {} void writeMessageToFd(int fd, kj::ArrayPtr> segments) { #ifdef _WIN32 auto oldMode = _setmode(fd, _O_BINARY); if (oldMode != _O_BINARY) { _setmode(fd, oldMode); KJ_FAIL_REQUIRE("Tried to write a message to a file descriptor that is in text mode. Set the " "file descriptor to binary mode by calling the _setmode Windows CRT function, or passing " "_O_BINARY to _open()."); } #endif kj::FdOutputStream stream(fd); writeMessage(stream, segments); } void readMessageCopyFromFd(int fd, MessageBuilder& target, ReaderOptions options, kj::ArrayPtr scratchSpace) { kj::FdInputStream stream(fd); readMessageCopy(stream, target, options, scratchSpace); } } // namespace capnp capnproto-c++-1.1.0/src/capnp/serialize-text-test.c++0000644000175000017500000001352714527152321023064 0ustar00kentonkenton00000000000000// Copyright (c) 2015 Philip Quinn. // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "serialize-text.h" #include #include #include #include #include "test-util.h" #include namespace capnp { namespace _ { // private namespace { KJ_TEST("TextCodec TestAllTypes") { MallocMessageBuilder builder; initTestMessage(builder.initRoot()); { // Plain output TextCodec codec; codec.setPrettyPrint(false); auto text = codec.encode(builder.getRoot()); auto stringify = kj::str(builder.getRoot()); KJ_EXPECT(text == stringify); MallocMessageBuilder reader; auto orphan = codec.decode(text, reader.getOrphanage()); auto structReader = orphan.getReader(); checkTestMessage(structReader); } { // Pretty output TextCodec codec; codec.setPrettyPrint(true); auto text = codec.encode(builder.getRoot()); auto stringify = prettyPrint(builder.getRoot()).flatten(); KJ_EXPECT(text == stringify); MallocMessageBuilder reader; auto orphan = codec.decode(text, reader.getOrphanage()); auto structReader = orphan.getReader(); checkTestMessage(structReader); } } KJ_TEST("TextCodec TestDefaults") { MallocMessageBuilder builder; initTestMessage(builder.initRoot()); TextCodec codec; auto text = codec.encode(builder.getRoot()); MallocMessageBuilder reader; auto orphan = codec.decode(text, reader.getOrphanage()); auto structReader = orphan.getReader(); checkTestMessage(structReader); } KJ_TEST("TextCodec TestListDefaults") { MallocMessageBuilder builder; initTestMessage(builder.initRoot()); TextCodec codec; auto text = codec.encode(builder.getRoot()); MallocMessageBuilder reader; auto orphan = codec.decode(text, reader.getOrphanage()); auto structReader = orphan.getReader(); checkTestMessage(structReader); } KJ_TEST("TextCodec raw text") { using TestType = capnproto_test::capnp::test::TestLateUnion; kj::String message = kj::str(R"(( foo = -123, bar = "bar", baz = 456, # Test Comment theUnion = ( qux = "qux" ), anotherUnion = ( corge = [ 7, 8, 9 ] ), ))"); MallocMessageBuilder builder; auto testType = builder.initRoot(); TextCodec codec; codec.decode(message, testType); auto reader = testType.asReader(); KJ_EXPECT(reader.getFoo() == -123); KJ_EXPECT(reader.getBar() == "bar"); KJ_EXPECT(reader.getBaz() == 456); KJ_EXPECT(reader.getTheUnion().isQux()); KJ_EXPECT(reader.getTheUnion().hasQux()); KJ_EXPECT(reader.getTheUnion().getQux() == "qux"); KJ_EXPECT(reader.getAnotherUnion().isCorge()); KJ_EXPECT(reader.getAnotherUnion().hasCorge()); KJ_EXPECT(reader.getAnotherUnion().getCorge().size() == 3); KJ_EXPECT(reader.getAnotherUnion().getCorge()[0] == 7); KJ_EXPECT(reader.getAnotherUnion().getCorge()[1] == 8); KJ_EXPECT(reader.getAnotherUnion().getCorge()[2] == 9); } KJ_TEST("TextCodec parse error") { auto message = "\n (,)"_kj; MallocMessageBuilder builder; auto root = builder.initRoot(); TextCodec codec; auto exception = KJ_ASSERT_NONNULL(kj::runCatchingExceptions( [&]() { codec.decode(message, root); })); KJ_EXPECT(exception.getFile() == "(capnp text input)"_kj); KJ_EXPECT(exception.getLine() == 2); KJ_EXPECT(exception.getDescription() == "3-6: Parse error: Empty list item.", exception.getDescription()); } KJ_TEST("text format implicitly coerces struct value from first field type") { // We don't actually use TextCodec here, but rather check how the compiler handled some constants // defined in test.capnp. It's the same parser code either way but this is easier. { auto s = test::TestImpliedFirstField::Reader().getTextStruct(); KJ_EXPECT(s.getText() == "foo"); KJ_EXPECT(s.getI() == 321); } { auto s = test::TEST_IMPLIED_FIRST_FIELD->getTextStruct(); KJ_EXPECT(s.getText() == "bar"); KJ_EXPECT(s.getI() == 321); } #if __GNUC__ && !__clang__ // GCC generates a spurious warning here... #pragma GCC diagnostic ignored "-Wmisleading-indentation" #endif { auto l = test::TEST_IMPLIED_FIRST_FIELD->getTextStructList(); KJ_ASSERT(l.size() == 2); { auto s = l[0]; KJ_EXPECT(s.getText() == "baz"); KJ_EXPECT(s.getI() == 321); } { auto s = l[1]; KJ_EXPECT(s.getText() == "qux"); KJ_EXPECT(s.getI() == 123); } } { auto s = test::TEST_IMPLIED_FIRST_FIELD->getIntGroup(); KJ_EXPECT(s.getI() == 123); KJ_EXPECT(s.getStr() == "corge"); } } } // namespace } // namespace _ (private) } // namespace capnp capnproto-c++-1.1.0/src/capnp/schema-parser-test.c++0000644000175000017500000002615314527152321022644 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #define CAPNP_TESTING_CAPNP 1 #include "schema-parser.h" #include #include "test-util.h" #include #include namespace capnp { namespace { #if _WIN32 #define ABS(x) "C:\\" x #else #define ABS(x) "/" x #endif class FakeFileReader final: public kj::Filesystem { public: void add(kj::StringPtr name, kj::StringPtr content) { root->openFile(cwd.evalNative(name), kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT) ->writeAll(content); } const kj::Directory& getRoot() const override { return *root; } const kj::Directory& getCurrent() const override { return *current; } kj::PathPtr getCurrentPath() const override { return cwd; } private: kj::Own root = kj::newInMemoryDirectory(kj::nullClock()); kj::Path cwd = kj::Path({}).evalNative(ABS("path/to/current/dir")); kj::Own current = root->openSubdir(cwd, kj::WriteMode::CREATE | kj::WriteMode::CREATE_PARENT); }; static uint64_t getFieldTypeFileId(StructSchema::Field field) { return field.getContainingStruct() .getDependency(field.getProto().getSlot().getType().getStruct().getTypeId()) .getProto().getScopeId(); } TEST(SchemaParser, Basic) { FakeFileReader reader; SchemaParser parser; parser.setDiskFilesystem(reader); reader.add("src/foo/bar.capnp", "@0x8123456789abcdef;\n" "struct Bar {\n" " baz @0: import \"baz.capnp\".Baz;\n" " corge @1: import \"../qux/corge.capnp\".Corge;\n" " grault @2: import \"/grault.capnp\".Grault;\n" " garply @3: import \"/garply.capnp\".Garply;\n" "}\n"); reader.add("src/foo/baz.capnp", "@0x823456789abcdef1;\n" "struct Baz {}\n"); reader.add("src/qux/corge.capnp", "@0x83456789abcdef12;\n" "struct Corge {}\n"); reader.add(ABS("usr/include/grault.capnp"), "@0x8456789abcdef123;\n" "struct Grault {}\n"); reader.add(ABS("opt/include/grault.capnp"), "@0x8000000000000001;\n" "struct WrongGrault {}\n"); reader.add(ABS("usr/local/include/garply.capnp"), "@0x856789abcdef1234;\n" "struct Garply {}\n"); kj::StringPtr importPath[] = { ABS("usr/include"), ABS("usr/local/include"), ABS("opt/include") }; ParsedSchema barSchema = parser.parseDiskFile( "foo2/bar2.capnp", "src/foo/bar.capnp", importPath); auto barProto = barSchema.getProto(); EXPECT_EQ(0x8123456789abcdefull, barProto.getId()); EXPECT_EQ("foo2/bar2.capnp", barProto.getDisplayName()); auto barStruct = barSchema.getNested("Bar"); auto barFields = barStruct.asStruct().getFields(); ASSERT_EQ(4u, barFields.size()); EXPECT_EQ("baz", barFields[0].getProto().getName()); EXPECT_EQ(0x823456789abcdef1ull, getFieldTypeFileId(barFields[0])); EXPECT_EQ("corge", barFields[1].getProto().getName()); EXPECT_EQ(0x83456789abcdef12ull, getFieldTypeFileId(barFields[1])); EXPECT_EQ("grault", barFields[2].getProto().getName()); EXPECT_EQ(0x8456789abcdef123ull, getFieldTypeFileId(barFields[2])); EXPECT_EQ("garply", barFields[3].getProto().getName()); EXPECT_EQ(0x856789abcdef1234ull, getFieldTypeFileId(barFields[3])); auto barStructs = barSchema.getAllNested(); ASSERT_EQ(1, barStructs.size()); EXPECT_EQ("Bar", barStructs[0].getUnqualifiedName()); barFields = barStructs[0].asStruct().getFields(); ASSERT_EQ(4u, barFields.size()); EXPECT_EQ("baz", barFields[0].getProto().getName()); EXPECT_EQ(0x823456789abcdef1ull, getFieldTypeFileId(barFields[0])); auto bazSchema = parser.parseDiskFile( "not/used/because/already/loaded", "src/foo/baz.capnp", importPath); EXPECT_EQ(0x823456789abcdef1ull, bazSchema.getProto().getId()); EXPECT_EQ("foo2/baz.capnp", bazSchema.getProto().getDisplayName()); auto bazStruct = bazSchema.getNested("Baz").asStruct(); EXPECT_EQ(bazStruct, barStruct.getDependency(bazStruct.getProto().getId())); auto corgeSchema = parser.parseDiskFile( "not/used/because/already/loaded", "src/qux/corge.capnp", importPath); EXPECT_EQ(0x83456789abcdef12ull, corgeSchema.getProto().getId()); EXPECT_EQ("qux/corge.capnp", corgeSchema.getProto().getDisplayName()); auto corgeStruct = corgeSchema.getNested("Corge").asStruct(); EXPECT_EQ(corgeStruct, barStruct.getDependency(corgeStruct.getProto().getId())); auto graultSchema = parser.parseDiskFile( "not/used/because/already/loaded", ABS("usr/include/grault.capnp"), importPath); EXPECT_EQ(0x8456789abcdef123ull, graultSchema.getProto().getId()); EXPECT_EQ("grault.capnp", graultSchema.getProto().getDisplayName()); auto graultStruct = graultSchema.getNested("Grault").asStruct(); EXPECT_EQ(graultStruct, barStruct.getDependency(graultStruct.getProto().getId())); // Try importing the other grault.capnp directly. It'll get the display name we specify since // it wasn't imported before. auto wrongGraultSchema = parser.parseDiskFile( "weird/display/name.capnp", ABS("opt/include/grault.capnp"), importPath); EXPECT_EQ(0x8000000000000001ull, wrongGraultSchema.getProto().getId()); EXPECT_EQ("weird/display/name.capnp", wrongGraultSchema.getProto().getDisplayName()); } TEST(SchemaParser, Constants) { // This is actually a test of the full dynamic API stack for constants, because the schemas for // constants are not actually accessible from the generated code API, so the only way to ever // get a ConstSchema is by parsing it. FakeFileReader reader; SchemaParser parser; parser.setDiskFilesystem(reader); reader.add("const.capnp", "@0x8123456789abcdef;\n" "const uint32Const :UInt32 = 1234;\n" "const listConst :List(Float32) = [1.25, 2.5, 3e4];\n" "const structConst :Foo = (bar = 123, baz = \"qux\");\n" "struct Foo {\n" " bar @0 :Int16;\n" " baz @1 :Text;\n" "}\n" "const genericConst :TestGeneric(Text) = (value = \"text\");\n" "struct TestGeneric(T) {\n" " value @0 :T;\n" "}\n"); ParsedSchema fileSchema = parser.parseDiskFile( "const.capnp", "const.capnp", nullptr); EXPECT_EQ(1234, fileSchema.getNested("uint32Const").asConst().as()); auto list = fileSchema.getNested("listConst").asConst().as(); ASSERT_EQ(3u, list.size()); EXPECT_EQ(1.25, list[0].as()); EXPECT_EQ(2.5, list[1].as()); EXPECT_EQ(3e4f, list[2].as()); auto structConst = fileSchema.getNested("structConst").asConst().as(); EXPECT_EQ(123, structConst.get("bar").as()); EXPECT_EQ("qux", structConst.get("baz").as()); auto genericConst = fileSchema.getNested("genericConst").asConst().as(); EXPECT_EQ("text", genericConst.get("value").as()); } void expectSourceInfo(schema::Node::SourceInfo::Reader sourceInfo, uint64_t expectedId, kj::StringPtr expectedComment, std::initializer_list expectedMembers) { KJ_EXPECT(sourceInfo.getId() == expectedId, sourceInfo, expectedId); KJ_EXPECT(sourceInfo.getDocComment() == expectedComment, sourceInfo, expectedComment); auto members = sourceInfo.getMembers(); KJ_ASSERT(members.size() == expectedMembers.size()); for (auto i: kj::indices(expectedMembers)) { KJ_EXPECT(members[i].getDocComment() == expectedMembers.begin()[i], members[i], expectedMembers.begin()[i]); } } TEST(SchemaParser, SourceInfo) { FakeFileReader reader; SchemaParser parser; parser.setDiskFilesystem(reader); reader.add("foo.capnp", "@0x84a2c6051e1061ed;\n" "# file doc comment\n" "\n" "struct Foo @0xc6527d0a670dc4c3 {\n" " # struct doc comment\n" " # second line\n" "\n" " bar @0 :UInt32;\n" " # field doc comment\n" " baz :group {\n" " # group doc comment\n" " qux @1 :Text;\n" " # group field doc comment\n" " }\n" "}\n" "\n" "enum Corge @0xae08878f1a016f14 {\n" " # enum doc comment\n" " grault @0;\n" " # enumerant doc comment\n" " garply @1;\n" "}\n" "\n" "interface Waldo @0xc0f1b0aff62b761e {\n" " # interface doc comment\n" " fred @0 (plugh :Int32) -> (xyzzy :Text);\n" " # method doc comment\n" "}\n" "\n" "struct Thud @0xcca9972702b730b4 {}\n" "# post-comment\n"); ParsedSchema file = parser.parseDiskFile( "foo.capnp", "foo.capnp", nullptr); ParsedSchema foo = file.getNested("Foo"); expectSourceInfo(file.getSourceInfo(), 0x84a2c6051e1061edull, "file doc comment\n", {}); expectSourceInfo(foo.getSourceInfo(), 0xc6527d0a670dc4c3ull, "struct doc comment\nsecond line\n", { "field doc comment\n", "group doc comment\n" }); auto group = foo.asStruct().getFieldByName("baz").getType().asStruct(); expectSourceInfo(KJ_ASSERT_NONNULL(parser.getSourceInfo(group)), group.getProto().getId(), "group doc comment\n", { "group field doc comment\n" }); ParsedSchema corge = file.getNested("Corge"); expectSourceInfo(corge.getSourceInfo(), 0xae08878f1a016f14, "enum doc comment\n", { "enumerant doc comment\n", "" }); ParsedSchema waldo = file.getNested("Waldo"); expectSourceInfo(waldo.getSourceInfo(), 0xc0f1b0aff62b761e, "interface doc comment\n", { "method doc comment\n" }); ParsedSchema thud = file.getNested("Thud"); expectSourceInfo(thud.getSourceInfo(), 0xcca9972702b730b4, "post-comment\n", {}); } TEST(SchemaParser, SetFileIdsRequired) { FakeFileReader reader; reader.add("no-file-id.capnp", "const foo :Int32 = 123;\n"); { SchemaParser parser; parser.setDiskFilesystem(reader); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("File does not declare an ID.", parser.parseDiskFile("no-file-id.capnp", "no-file-id.capnp", nullptr)); } { SchemaParser parser; parser.setDiskFilesystem(reader); parser.setFileIdsRequired(false); auto fileSchema = parser.parseDiskFile("no-file-id.capnp", "no-file-id.capnp", nullptr); KJ_EXPECT(fileSchema.getNested("foo").asConst().as() == 123); } } } // namespace } // namespace capnp capnproto-c++-1.1.0/src/capnp/rpc-twoparty.h0000644000175000017500000002741714712011043021462 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "rpc.h" #include #include #include #include #include CAPNP_BEGIN_HEADER namespace capnp { namespace rpc { namespace twoparty { typedef VatId SturdyRefHostId; // For backwards-compatibility with version 0.4. } } typedef VatNetwork TwoPartyVatNetworkBase; class TwoPartyVatNetwork: public TwoPartyVatNetworkBase, private TwoPartyVatNetworkBase::Connection, private RpcFlowController::WindowGetter { // A `VatNetwork` that consists of exactly two parties communicating over an arbitrary byte // stream. This is used to implement the common case of a client/server network. // // See `ez-rpc.h` for a simple interface for setting up two-party clients and servers. // Use `TwoPartyVatNetwork` only if you need the advanced features. public: TwoPartyVatNetwork(MessageStream& msgStream, rpc::twoparty::Side side, ReaderOptions receiveOptions = ReaderOptions(), const kj::MonotonicClock& clock = kj::systemCoarseMonotonicClock()); TwoPartyVatNetwork(MessageStream& msgStream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions = ReaderOptions(), const kj::MonotonicClock& clock = kj::systemCoarseMonotonicClock()); TwoPartyVatNetwork(kj::AsyncIoStream& stream, rpc::twoparty::Side side, ReaderOptions receiveOptions = ReaderOptions(), const kj::MonotonicClock& clock = kj::systemCoarseMonotonicClock()); TwoPartyVatNetwork(kj::AsyncCapabilityStream& stream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions = ReaderOptions(), const kj::MonotonicClock& clock = kj::systemCoarseMonotonicClock()); // To support FD passing, pass an AsyncCapabilityStream or a MessageStream which supports // fd passing, and `maxFdsPerMessage`, which specifies the maximum number of file descriptors // to accept from the peer in any one RPC message. It is important to keep maxFdsPerMessage // low in order to stop DoS attacks that fill up your FD table. // // Note that this limit applies only to incoming messages; outgoing messages are allowed to have // more FDs. Sometimes it makes sense to enforce a limit of zero in one direction while having // a non-zero limit in the other. For example, in a supervisor/sandbox scenario, typically there // are many use cases for passing FDs from supervisor to sandbox but no use case for vice versa. // The supervisor may be configured not to accept any FDs from the sandbox in order to reduce // risk of DoS attacks. // // clock is used for calculating the oldest queued message age, which is a useful metric for // detecting queue overload ~TwoPartyVatNetwork() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(TwoPartyVatNetwork); kj::Promise onDisconnect() { return disconnectPromise.addBranch(); } // Returns a promise that resolves when the peer disconnects. rpc::twoparty::Side getSide() { return side; } size_t getCurrentQueueSize() { return currentQueueSize; } // Get the number of bytes worth of outgoing messages that are currently queued in memory waiting // to be sent on this connection. This may be useful for backpressure. size_t getCurrentQueueCount() { return queuedMessages.size(); } // Get the count of outgoing messages that are currently queued in memory waiting // to be sent on this connection. This may be useful for backpressure. kj::Duration getOutgoingMessageWaitTime(); // Get how long the current outgoing message has been waiting to be sent on this connection. // Returns 0 if the queue is empty. This may be useful for backpressure. // implements VatNetwork ----------------------------------------------------- kj::Maybe> connect( rpc::twoparty::VatId::Reader ref) override; kj::Promise> accept() override; private: class OutgoingMessageImpl; class IncomingMessageImpl; kj::OneOf> stream; // The underlying stream, which we may or may not own. Get a reference to // this with getStream, rather than reading it directly. uint maxFdsPerMessage; rpc::twoparty::Side side; MallocMessageBuilder peerVatId; ReaderOptions receiveOptions; bool accepted = false; bool solSndbufUnimplemented = false; // Whether stream.getsockopt(SO_SNDBUF) has been observed to throw UNIMPLEMENTED. kj::Canceler readCanceler; kj::Maybe readCancelReason; // Used to propagate write errors into (permanent) read errors. kj::Maybe> previousWrite; // Resolves when the previous write completes. This effectively serves as the write queue. // Becomes null when shutdown() is called. kj::Own>> acceptFulfiller; // Fulfiller for the promise returned by acceptConnectionAsRefHost() on the client side, or the // second call on the server side. Never fulfilled, because there is only one connection. kj::ForkedPromise disconnectPromise = nullptr; kj::Vector> queuedMessages; size_t currentQueueSize = 0; const kj::MonotonicClock& clock; kj::TimePoint currentOutgoingMessageSendTime; class FulfillerDisposer: public kj::Disposer { // Hack: TwoPartyVatNetwork is both a VatNetwork and a VatNetwork::Connection. When the RPC // system detects (or initiates) a disconnection, it drops its reference to the Connection. // When all references have been dropped, then we want disconnectPromise to be fulfilled. // So we hand out Owns with this disposer attached, so that we can detect when // they are dropped. public: mutable kj::Own> fulfiller; mutable uint refcount = 0; void disposeImpl(void* pointer) const override; }; FulfillerDisposer disconnectFulfiller; TwoPartyVatNetwork( kj::OneOf>&& stream, uint maxFdsPerMessage, rpc::twoparty::Side side, ReaderOptions receiveOptions, const kj::MonotonicClock& clock); MessageStream& getStream(); kj::Own asConnection(); // Returns a pointer to this with the disposer set to disconnectFulfiller. // implements Connection ----------------------------------------------------- kj::Own newStream() override; rpc::twoparty::VatId::Reader getPeerVatId() override; kj::Own newOutgoingMessage(uint firstSegmentWordSize) override; kj::Promise>> receiveIncomingMessage() override; kj::Promise shutdown() override; // implements WindowGetter --------------------------------------------------- size_t getWindow() override; }; class TwoPartyServer: private kj::TaskSet::ErrorHandler { // Convenience class which implements a simple server which accepts connections on a listener // socket and services them as two-party connections. public: explicit TwoPartyServer(Capability::Client bootstrapInterface, kj::Maybe> traceEncoder = nullptr); // `traceEncoder`, if provided, will be passed on to `rpcSystem.setTraceEncoder()`. void accept(kj::Own&& connection); void accept(kj::Own&& connection, uint maxFdsPerMessage); // Accepts the connection for servicing. kj::Promise accept(kj::AsyncIoStream& connection) KJ_WARN_UNUSED_RESULT; kj::Promise accept(kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage) KJ_WARN_UNUSED_RESULT; // Accept connection without taking ownership. The returned promise resolves when the client // disconnects. Dropping the promise forcefully cancels the RPC protocol. // // You probably can't do anything with `connection` after the RPC protocol has terminated, other // than to close it. The main reason to use these methods rather than the ownership-taking ones // is if your stream object becomes invalid outside some scope, so you want to make sure to // cancel all usage of it before that by cancelling the promise. kj::Promise listen(kj::ConnectionReceiver& listener); // Listens for connections on the given listener. The returned promise never resolves unless an // exception is thrown while trying to accept. You may discard the returned promise to cancel // listening. kj::Promise listenCapStreamReceiver( kj::ConnectionReceiver& listener, uint maxFdsPerMessage); // Listen with support for FD transfers. `listener.accept()` must return instances of // AsyncCapabilityStream, otherwise this will crash. kj::Promise drain() { return tasks.onEmpty(); } // Resolves when all clients have disconnected. // // Only considers clients whose connections TwoPartyServer took ownership of. private: Capability::Client bootstrapInterface; kj::Maybe> traceEncoder; kj::TaskSet tasks; struct AcceptedConnection; void taskFailed(kj::Exception&& exception) override; }; class TwoPartyClient { // Convenience class which implements a simple client. public: explicit TwoPartyClient(kj::AsyncIoStream& connection); explicit TwoPartyClient(kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage); TwoPartyClient(kj::AsyncIoStream& connection, Capability::Client bootstrapInterface, rpc::twoparty::Side side = rpc::twoparty::Side::CLIENT); TwoPartyClient(kj::AsyncCapabilityStream& connection, uint maxFdsPerMessage, Capability::Client bootstrapInterface, rpc::twoparty::Side side = rpc::twoparty::Side::CLIENT); Capability::Client bootstrap(); // Get the server's bootstrap interface. inline kj::Promise onDisconnect() { return network.onDisconnect(); } void setTraceEncoder(kj::Function func); // Forwarded to rpcSystem.setTraceEncoder(). size_t getCurrentQueueSize() { return network.getCurrentQueueSize(); } size_t getCurrentQueueCount() { return network.getCurrentQueueCount(); } kj::Duration getOutgoingMessageWaitTime() { return network.getOutgoingMessageWaitTime(); } private: TwoPartyVatNetwork network; RpcSystem rpcSystem; }; } // namespace capnp CAPNP_END_HEADER capnproto-c++-1.1.0/src/kj/0000755000175000017500000000000014731562205016142 5ustar00kentonkenton00000000000000capnproto-c++-1.1.0/src/kj/common.c++0000644000175000017500000000355014527152321017724 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "common.h" #include "debug.h" #include namespace kj { namespace _ { // private void inlineRequireFailure(const char* file, int line, const char* expectation, const char* macroArgs, const char* message) { if (message == nullptr) { Debug::Fault f(file, line, kj::Exception::Type::FAILED, expectation, macroArgs); f.fatal(); } else { Debug::Fault f(file, line, kj::Exception::Type::FAILED, expectation, macroArgs, message); f.fatal(); } } void unreachable() { KJ_FAIL_ASSERT("Supposedly-unreachable branch executed."); // Really make sure we abort. KJ_KNOWN_UNREACHABLE(abort()); } } // namespace _ (private) } // namespace kj capnproto-c++-1.1.0/src/kj/async.c++0000644000175000017500000031314614712011043017545 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #undef _FORTIFY_SOURCE // If _FORTIFY_SOURCE is defined, longjmp will complain when it detects the stack // pointer moving in the "wrong direction", thinking you're jumping to a non-existent // stack frame. But we use longjmp to jump between different stacks to implement fibers, // so this check isn't appropriate for us. #if _WIN32 || __CYGWIN__ #include #elif __APPLE__ // getcontext() and friends are marked deprecated on MacOS but seemingly no replacement is // provided. It appears as if they deprecated it solely because the standards bodies deprecated it, // which they seemingly did mainly because the proper semantics are too difficult for them to // define. I doubt MacOS would actually remove these functions as they are widely used. But if they // do, then I guess we'll need to fall back to using setjmp()/longjmp(), and some sort of hack // involving sigaltstack() (and generating a fake signal I guess) in order to initialize the fiber // in the first place. Or we could use assembly, I suppose. Either way, ick. #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #define _XOPEN_SOURCE // Must be defined to see getcontext() on MacOS. #endif #include "async.h" #include "debug.h" #include "vector.h" #include "threadlocal.h" #include "mutex.h" #include "one-of.h" #include "function.h" #include "list.h" #include #include #if _WIN32 || __CYGWIN__ #include // for Sleep(0) and fibers #include #else #if KJ_USE_FIBERS #include #include // for fibers #endif #include // mmap(), for allocating new stacks #include // sysconf() #include #endif #if !_WIN32 #include // just for sched_yield() #endif #if !KJ_NO_RTTI #include #if __GNUC__ #include #endif #endif #include #if KJ_HAS_COMPILER_FEATURE(address_sanitizer) // Clang's address sanitizer requires special hints when switching fibers, especially in order for // stack-use-after-return handling to work right. // // TODO(someday): Does GCC's sanitizer, flagged by __SANITIZE_ADDRESS__, have these hints too? I // don't know and am not in a position to test, so I'm assuming not for now. #include #else // Nop the hints so that we don't have to put #ifdefs around every use. #define __sanitizer_start_switch_fiber(...) #define __sanitizer_finish_switch_fiber(...) #endif #if _MSC_VER && !__clang__ // MSVC's atomic intrinsics are weird and different, whereas the C++ standard atomics match the GCC // builtins -- except for requiring the obnoxious std::atomic wrapper. So, on MSVC let's just // #define the builtins based on the C++ library, reinterpret-casting native types to // std::atomic... this is cheating but ugh, whatever. template static std::atomic* reinterpretAtomic(T* ptr) { return reinterpret_cast*>(ptr); } #define __atomic_store_n(ptr, val, order) \ std::atomic_store_explicit(reinterpretAtomic(ptr), val, order) #define __atomic_load_n(ptr, order) \ std::atomic_load_explicit(reinterpretAtomic(ptr), order) #define __atomic_compare_exchange_n(ptr, expected, desired, weak, succ, fail) \ std::atomic_compare_exchange_strong_explicit( \ reinterpretAtomic(ptr), expected, desired, succ, fail) #define __atomic_exchange_n(ptr, val, order) \ std::atomic_exchange_explicit(reinterpretAtomic(ptr), val, order) #define __ATOMIC_RELAXED std::memory_order_relaxed #define __ATOMIC_ACQUIRE std::memory_order_acquire #define __ATOMIC_RELEASE std::memory_order_release #endif namespace kj { namespace { KJ_THREADLOCAL_PTR(DisallowAsyncDestructorsScope) disallowAsyncDestructorsScope = nullptr; } // namespace AsyncObject::~AsyncObject() { if (disallowAsyncDestructorsScope != nullptr) { // If we try to do the KJ_FAIL_REQUIRE here (declaring `~AsyncObject()` itself to be noexcept), // it seems to have a non-negligible performance impact in the HTTP benchmark. My guess is that // it's because it breaks inlining of `~AsyncObject()` into various subclass destructors that // are defined inside this file, which are some of the biggest ones. By forcing the actual // failure code out into a separate function we get a little performance boost. failed(); } } void AsyncObject::failed() noexcept { // Since the method is noexcept, this will abort the process. KJ_FAIL_REQUIRE( kj::str("KJ async object being destroyed when not allowed: ", disallowAsyncDestructorsScope->reason)); } DisallowAsyncDestructorsScope::DisallowAsyncDestructorsScope(kj::StringPtr reason) : reason(reason), previousValue(disallowAsyncDestructorsScope) { requireOnStack(this, "DisallowAsyncDestructorsScope must be allocated on the stack."); disallowAsyncDestructorsScope = this; } DisallowAsyncDestructorsScope::~DisallowAsyncDestructorsScope() { disallowAsyncDestructorsScope = previousValue; } AllowAsyncDestructorsScope::AllowAsyncDestructorsScope() : previousValue(disallowAsyncDestructorsScope) { requireOnStack(this, "AllowAsyncDestructorsScope must be allocated on the stack."); disallowAsyncDestructorsScope = nullptr; } AllowAsyncDestructorsScope::~AllowAsyncDestructorsScope() { disallowAsyncDestructorsScope = previousValue; } // ======================================================================================= namespace { KJ_THREADLOCAL_PTR(EventLoop) threadLocalEventLoop = nullptr; #define _kJ_ALREADY_READY reinterpret_cast< ::kj::_::Event*>(1) EventLoop& currentEventLoop() { EventLoop* loop = threadLocalEventLoop; KJ_REQUIRE(loop != nullptr, "No event loop is running on this thread."); return *loop; } class RootEvent: public _::Event { public: RootEvent(_::PromiseNode* node, void* traceAddr, SourceLocation location) : Event(location), node(node), traceAddr(traceAddr) {} bool fired = false; Maybe> fire() override { fired = true; return nullptr; } void traceEvent(_::TraceBuilder& builder) override { node->tracePromise(builder, true); builder.add(traceAddr); } private: _::PromiseNode* node; void* traceAddr; }; struct DummyFunctor { void operator()() {}; }; } // namespace // ======================================================================================= void END_CANCELER_STACK_START_CANCELEE_STACK() {} // Dummy symbol used when reporting how a Canceler was canceled. We end up combining two stack // traces into one and we use this as a separator. Canceler::~Canceler() noexcept(false) { if (isEmpty()) return; cancel(getDestructionReason( reinterpret_cast(&END_CANCELER_STACK_START_CANCELEE_STACK), Exception::Type::DISCONNECTED, __FILE__, __LINE__, "operation canceled"_kj)); } void Canceler::cancel(StringPtr cancelReason) { if (isEmpty()) return; // We can't use getDestructionReason() here because if an exception is in-flight, it would use // that exception, totally discarding the reason given by the caller. This would probably be // unexpected. The caller can always use getDestructionReason() themselves if desired. cancel(Exception(Exception::Type::DISCONNECTED, __FILE__, __LINE__, kj::str(cancelReason))); } void Canceler::cancel(const Exception& exception) { for (;;) { KJ_IF_MAYBE(a, list) { a->unlink(); a->cancel(kj::cp(exception)); } else { break; } } } void Canceler::release() { for (;;) { KJ_IF_MAYBE(a, list) { a->unlink(); } else { break; } } } Canceler::AdapterBase::AdapterBase(Canceler& canceler) : prev(canceler.list), next(canceler.list) { canceler.list = *this; KJ_IF_MAYBE(n, next) { n->prev = next; } } Canceler::AdapterBase::~AdapterBase() noexcept(false) { unlink(); } void Canceler::AdapterBase::unlink() { KJ_IF_MAYBE(p, prev) { *p = next; } KJ_IF_MAYBE(n, next) { n->prev = prev; } next = nullptr; prev = nullptr; } Canceler::AdapterImpl::AdapterImpl(kj::PromiseFulfiller& fulfiller, Canceler& canceler, kj::Promise inner) : AdapterBase(canceler), fulfiller(fulfiller), inner(inner.then( [&fulfiller]() { fulfiller.fulfill(); }, [&fulfiller](kj::Exception&& e) { fulfiller.reject(kj::mv(e)); }) .eagerlyEvaluate(nullptr)) {} void Canceler::AdapterImpl::cancel(kj::Exception&& e) { fulfiller.reject(kj::mv(e)); inner = nullptr; } // ======================================================================================= TaskSet::TaskSet(TaskSet::ErrorHandler& errorHandler, SourceLocation location) : errorHandler(errorHandler), location(location) {} class TaskSet::Task final: public _::PromiseArenaMember, public _::Event { public: Task(_::OwnPromiseNode&& nodeParam, TaskSet& taskSet) : Event(taskSet.location), taskSet(taskSet), node(kj::mv(nodeParam)) { node->setSelfPointer(&node); node->onReady(this); } void destroy() override { freePromise(this); } OwnTask pop() { KJ_IF_MAYBE(n, next) { n->get()->prev = prev; } OwnTask self = kj::mv(KJ_ASSERT_NONNULL(*prev)); KJ_ASSERT(self.get() == this); *prev = kj::mv(next); next = nullptr; prev = nullptr; return self; } Maybe next; Maybe* prev = nullptr; kj::String trace() { void* space[32]; _::TraceBuilder builder(space); node->tracePromise(builder, false); return kj::str("task: ", builder); } protected: Maybe> fire() override { // Get the result. _::ExceptionOr<_::Void> result; node->get(result); // Delete the node, catching any exceptions. KJ_IF_MAYBE(exception, kj::runCatchingExceptions([this]() { node = nullptr; })) { result.addException(kj::mv(*exception)); } // Remove from the task list. Do this before calling taskFailed(), so that taskFailed() can // safely call clear(). auto self = pop(); // We'll also process onEmpty() now, just in case `taskFailed()` actually destroys the whole // `TaskSet`. KJ_IF_MAYBE(f, taskSet.emptyFulfiller) { if (taskSet.tasks == nullptr) { f->get()->fulfill(); taskSet.emptyFulfiller = nullptr; } } // Call the error handler if there was an exception. KJ_IF_MAYBE(e, result.exception) { taskSet.errorHandler.taskFailed(kj::mv(*e)); } return Own(mv(self)); } void traceEvent(_::TraceBuilder& builder) override { // Pointing out the ErrorHandler's taskFailed() implementation will usually identify the // particular TaskSet that contains this event. builder.add(_::getMethodStartAddress(taskSet.errorHandler, &ErrorHandler::taskFailed)); } private: TaskSet& taskSet; _::OwnPromiseNode node; }; TaskSet::~TaskSet() noexcept(false) { // You could argue it is dubious, but some applications would like for the destructor of a // task to be able to schedule new tasks. So when we cancel our tasks... we might find new // tasks added! We'll have to repeatedly cancel. Additionally, we need to make sure that we destroy // the items in a loop to prevent any issues with stack overflow. while (tasks != nullptr) { auto removed = KJ_REQUIRE_NONNULL(tasks)->pop(); } } void TaskSet::add(Promise&& promise) { auto task = _::appendPromise(_::PromiseNode::from(kj::mv(promise)), *this); KJ_IF_MAYBE(head, tasks) { head->get()->prev = &task->next; task->next = kj::mv(tasks); } task->prev = &tasks; tasks = kj::mv(task); } kj::String TaskSet::trace() { kj::Vector traces; Maybe* ptr = &tasks; for (;;) { KJ_IF_MAYBE(task, *ptr) { traces.add(task->get()->trace()); ptr = &task->get()->next; } else { break; } } return kj::strArray(traces, "\n"); } Promise TaskSet::onEmpty() { KJ_IF_MAYBE(fulfiller, emptyFulfiller) { if (fulfiller->get()->isWaiting()) { KJ_FAIL_REQUIRE("onEmpty() can only be called once at a time"); } } if (tasks == nullptr) { return READY_NOW; } else { auto paf = newPromiseAndFulfiller(); emptyFulfiller = kj::mv(paf.fulfiller); return kj::mv(paf.promise); } } void TaskSet::clear() { tasks = nullptr; KJ_IF_MAYBE(fulfiller, emptyFulfiller) { fulfiller->get()->fulfill(); } } // ======================================================================================= namespace { #if _WIN32 || __CYGWIN__ thread_local void* threadMainFiber = nullptr; void* getMainWin32Fiber() { return threadMainFiber; } #endif inline void ensureThreadCanRunFibers() { #if _WIN32 || __CYGWIN__ // Make sure the current thread has been converted to a fiber. void* fiber = threadMainFiber; if (fiber == nullptr) { // Thread not initialized. Convert it to a fiber now. // Note: Unfortunately, if the application has already converted the thread to a fiber, I // guess this will fail. But trying to call GetCurrentFiber() when the thread isn't a fiber // doesn't work (it returns null on WINE but not on real windows, ugh). So I guess we're // just incompatible with the application doing anything with fibers, which is sad. threadMainFiber = fiber = ConvertThreadToFiber(nullptr); } #endif } } // namespace namespace _ { class FiberStack final { // A class containing a fiber stack impl. This is separate from fiber // promises since it lets us move the stack itself around and reuse it. public: FiberStack(size_t stackSize); ~FiberStack() noexcept(false); struct SynchronousFunc { kj::FunctionParam& func; kj::Maybe exception; }; void initialize(FiberBase& fiber); void initialize(SynchronousFunc& syncFunc); void reset() { main = {}; } void switchToFiber(); void switchToMain(); void trace(TraceBuilder& builder) { // TODO(someday): Trace through fiber stack? Can it be done??? builder.add(getMethodStartAddress(*this, &FiberStack::trace)); } private: size_t stackSize; OneOf main; friend class FiberBase; friend class FiberPool::Impl; struct StartRoutine; #if KJ_USE_FIBERS #if _WIN32 || __CYGWIN__ void* osFiber; #else struct Impl; Impl* impl; #endif #endif [[noreturn]] void run(); bool isReset() { return main == nullptr; } }; } // namespace _ #if __linux__ // TODO(someday): Support core-local freelists on OSs other than Linux. The only tricky part is // finding what to use instead of sched_getcpu() to get the current CPU ID. #define USE_CORE_LOCAL_FREELISTS 1 #endif #if USE_CORE_LOCAL_FREELISTS static const size_t CACHE_LINE_SIZE = 64; // Most modern architectures have 64-byte cache lines. #endif class FiberPool::Impl final: private Disposer { public: Impl(size_t stackSize): stackSize(stackSize) {} ~Impl() noexcept(false) { #if USE_CORE_LOCAL_FREELISTS if (coreLocalFreelists != nullptr) { KJ_DEFER(free(coreLocalFreelists)); for (uint i: kj::zeroTo(nproc)) { for (auto stack: coreLocalFreelists[i].stacks) { if (stack != nullptr) { delete stack; } } } } #endif // Make sure we're not leaking anything from the global freelist either. auto lock = freelist.lockExclusive(); auto dangling = kj::mv(*lock); for (auto& stack: dangling) { delete stack; } } void setMaxFreelist(size_t count) { maxFreelist = count; } size_t getFreelistSize() const { return freelist.lockShared()->size(); } void useCoreLocalFreelists() { #if USE_CORE_LOCAL_FREELISTS if (coreLocalFreelists != nullptr) { // Ignore repeat call. return; } int nproc_; KJ_SYSCALL(nproc_ = sysconf(_SC_NPROCESSORS_CONF)); nproc = nproc_; void* allocPtr; size_t totalSize = nproc * sizeof(CoreLocalFreelist); int error = posix_memalign(&allocPtr, CACHE_LINE_SIZE, totalSize); if (error != 0) { KJ_FAIL_SYSCALL("posix_memalign", error); } memset(allocPtr, 0, totalSize); coreLocalFreelists = reinterpret_cast(allocPtr); #endif } Own<_::FiberStack> takeStack() const { // Get a stack from the pool. The disposer on the returned Own pointer will return the stack // to the pool, provided that reset() has been called to indicate that the stack is not in // a weird state. #if USE_CORE_LOCAL_FREELISTS KJ_IF_MAYBE(core, lookupCoreLocalFreelist()) { for (auto& stackPtr: core->stacks) { _::FiberStack* result = __atomic_exchange_n(&stackPtr, nullptr, __ATOMIC_ACQUIRE); if (result != nullptr) { // Found a stack in this slot! return { result, *this }; } } // No stacks found, fall back to global freelist. } #endif { auto lock = freelist.lockExclusive(); if (!lock->empty()) { _::FiberStack* result = lock->back(); lock->pop_back(); return { result, *this }; } } _::FiberStack* result = new _::FiberStack(stackSize); return { result, *this }; } private: size_t stackSize; size_t maxFreelist = kj::maxValue; MutexGuarded> freelist; #if USE_CORE_LOCAL_FREELISTS struct CoreLocalFreelist { union { _::FiberStack* stacks[2]; // For now, we don't try to freelist more than 2 stacks per core. If you have three or more // threads interleaved on a core, chances are you have bigger problems... byte padToCacheLine[CACHE_LINE_SIZE]; // We don't want two core-local freelists to live in the same cache line, otherwise the // cores will fight over ownership of that line. }; }; uint nproc; CoreLocalFreelist* coreLocalFreelists = nullptr; kj::Maybe lookupCoreLocalFreelist() const { if (coreLocalFreelists == nullptr) { return nullptr; } else { int cpu = sched_getcpu(); if (cpu >= 0) { // TODO(perf): Perhaps two hyperthreads on the same physical core should share a freelist? // But I don't know how to find out if the system uses hyperthreading. return coreLocalFreelists[cpu]; } else { static bool logged = false; if (!logged) { KJ_LOG(ERROR, "invalid cpu number from sched_getcpu()?", cpu, nproc); logged = true; } return nullptr; } } } #endif void disposeImpl(void* pointer) const { _::FiberStack* stack = reinterpret_cast<_::FiberStack*>(pointer); KJ_DEFER(delete stack); // Verify that the stack was reset before returning, otherwise it might be in a weird state // where we don't want to reuse it. if (stack->isReset()) { #if USE_CORE_LOCAL_FREELISTS KJ_IF_MAYBE(core, lookupCoreLocalFreelist()) { for (auto& stackPtr: core->stacks) { stack = __atomic_exchange_n(&stackPtr, stack, __ATOMIC_RELEASE); if (stack == nullptr) { // Cool, we inserted the stack into an unused slot. We're done. return; } } // All slots were occupied, so we inserted the new stack in the front, pushed the rest back, // and now `stack` refers to the stack that fell off the end of the core-local list. That // needs to go into the global freelist. } #endif auto lock = freelist.lockExclusive(); lock->push_back(stack); if (lock->size() > maxFreelist) { stack = lock->front(); lock->pop_front(); } else { stack = nullptr; } } } }; FiberPool::FiberPool(size_t stackSize) : impl(kj::heap(stackSize)) {} FiberPool::~FiberPool() noexcept(false) {} void FiberPool::setMaxFreelist(size_t count) { impl->setMaxFreelist(count); } size_t FiberPool::getFreelistSize() const { return impl->getFreelistSize(); } void FiberPool::useCoreLocalFreelists() { impl->useCoreLocalFreelists(); } void FiberPool::runSynchronously(kj::FunctionParam func) const { ensureThreadCanRunFibers(); _::FiberStack::SynchronousFunc syncFunc { func, nullptr }; { auto stack = impl->takeStack(); stack->initialize(syncFunc); stack->switchToFiber(); stack->reset(); // safe to reuse } KJ_IF_MAYBE(e, syncFunc.exception) { kj::throwRecoverableException(kj::mv(*e)); } } namespace _ { // private class LoggingErrorHandler: public TaskSet::ErrorHandler { public: static LoggingErrorHandler instance; void taskFailed(kj::Exception&& exception) override { KJ_LOG(ERROR, "Uncaught exception in daemonized task.", exception); } }; LoggingErrorHandler LoggingErrorHandler::instance = LoggingErrorHandler(); } // namespace _ (private) // ======================================================================================= struct Executor::Impl { Impl(EventLoop& loop): state(loop) {} struct State { // Queues of notifications from other threads that need this thread's attention. State(EventLoop& loop): loop(loop) {} kj::Maybe loop; // Becomes null when the loop is destroyed. List<_::XThreadEvent, &_::XThreadEvent::targetLink> start; List<_::XThreadEvent, &_::XThreadEvent::targetLink> cancel; List<_::XThreadEvent, &_::XThreadEvent::replyLink> replies; // Lists of events that need actioning by this thread. List<_::XThreadEvent, &_::XThreadEvent::targetLink> executing; // Events that have already been dispatched and are happily executing. This list is maintained // so that they can be canceled if the event loop exits. List<_::XThreadPaf, &_::XThreadPaf::link> fulfilled; // Set of XThreadPafs that have been fulfilled by another thread. bool waitingForCancel = false; // True if this thread is currently blocked waiting for some other thread to pump its // cancellation queue. If that other thread tries to block on *this* thread, then it could // deadlock -- it must take precautions against this. bool isDispatchNeeded() const { return !start.empty() || !cancel.empty() || !replies.empty() || !fulfilled.empty(); } void dispatchAll(Vector<_::XThreadEvent*>& eventsToCancelOutsideLock) { for (auto& event: start) { start.remove(event); executing.add(event); event.state = _::XThreadEvent::EXECUTING; event.armBreadthFirst(); } dispatchCancels(eventsToCancelOutsideLock); for (auto& event: replies) { replies.remove(event); event.onReadyEvent.armBreadthFirst(); } for (auto& event: fulfilled) { fulfilled.remove(event); event.state = _::XThreadPaf::DISPATCHED; event.onReadyEvent.armBreadthFirst(); } } void dispatchCancels(Vector<_::XThreadEvent*>& eventsToCancelOutsideLock) { for (auto& event: cancel) { cancel.remove(event); if (event.promiseNode == nullptr) { event.setDoneState(); } else { // We can't destroy the promiseNode while the mutex is locked, because we don't know // what the destructor might do. But, we *must* destroy it before acknowledging // cancellation. So we have to add it to a list to destroy later. eventsToCancelOutsideLock.add(&event); } } } }; kj::MutexGuarded state; // After modifying state from another thread, the loop's port.wake() must be called. void processAsyncCancellations(Vector<_::XThreadEvent*>& eventsToCancelOutsideLock) { // After calling dispatchAll() or dispatchCancels() with the lock held, it may be that some // cancellations require dropping the lock before destroying the promiseNode. In that case // those cancellations will be added to the eventsToCancelOutsideLock Vector passed to the // method. That vector must then be passed to processAsyncCancellations() as soon as the lock // is released. for (auto& event: eventsToCancelOutsideLock) { event->promiseNode = nullptr; event->disarm(); } // Now we need to mark all the events "done" under lock. auto lock = state.lockExclusive(); for (auto& event: eventsToCancelOutsideLock) { event->setDoneState(); } } void disconnect() { state.lockExclusive()->loop = nullptr; // Now that `loop` is set null in `state`, other threads will no longer try to manipulate our // lists, so we can access them without a lock. That's convenient because a bunch of the things // we want to do with them would require dropping the lock to avoid deadlocks. We'd end up // copying all the lists over into separate vectors first, dropping the lock, operating on // them, and then locking again. auto& s = state.getWithoutLock(); // We do, however, take and release the lock on the way out, to make sure anyone performing // a conditional wait for state changes gets a chance to have their wait condition re-checked. KJ_DEFER(state.lockExclusive()); for (auto& event: s.start) { KJ_ASSERT(event.state == _::XThreadEvent::QUEUED, event.state) { break; } s.start.remove(event); event.setDisconnected(); event.sendReply(); event.setDoneState(); } for (auto& event: s.executing) { KJ_ASSERT(event.state == _::XThreadEvent::EXECUTING, event.state) { break; } s.executing.remove(event); event.promiseNode = nullptr; event.setDisconnected(); event.sendReply(); event.setDoneState(); } for (auto& event: s.cancel) { KJ_ASSERT(event.state == _::XThreadEvent::CANCELING, event.state) { break; } s.cancel.remove(event); event.promiseNode = nullptr; event.setDoneState(); } // The replies list "should" be empty, because any locally-initiated tasks should have been // canceled before destroying the EventLoop. if (!s.replies.empty()) { KJ_LOG(ERROR, "EventLoop destroyed with cross-thread event replies outstanding"); for (auto& event: s.replies) { s.replies.remove(event); } } // Similarly for cross-thread fulfillers. The waiting tasks should have been canceled. if (!s.fulfilled.empty()) { KJ_LOG(ERROR, "EventLoop destroyed with cross-thread fulfiller replies outstanding"); for (auto& event: s.fulfilled) { s.fulfilled.remove(event); event.state = _::XThreadPaf::DISPATCHED; } } }}; namespace _ { // (private) XThreadEvent::XThreadEvent( ExceptionOrValue& result, const Executor& targetExecutor, EventLoop& loop, void* funcTracePtr, SourceLocation location) : Event(loop, location), result(result), funcTracePtr(funcTracePtr), targetExecutor(targetExecutor.addRef()) {} void XThreadEvent::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // We can't safely trace into another thread, so we'll stop here. builder.add(funcTracePtr); } void XThreadEvent::ensureDoneOrCanceled() { if (__atomic_load_n(&state, __ATOMIC_ACQUIRE) != DONE) { auto lock = targetExecutor->impl->state.lockExclusive(); const EventLoop* loop; KJ_IF_MAYBE(l, lock->loop) { loop = l; } else { // Target event loop is already dead, so we know it's already working on transitioning all // events to the DONE state. We can just wait. lock.wait([&](auto&) { return state == DONE; }); return; } switch (state) { case UNUSED: // Nothing to do. break; case QUEUED: lock->start.remove(*this); // No wake needed since we removed work rather than adding it. state = DONE; break; case EXECUTING: { lock->executing.remove(*this); lock->cancel.add(*this); state = CANCELING; KJ_IF_MAYBE(p, loop->port) { p->wake(); } Maybe maybeSelfExecutor = nullptr; if (threadLocalEventLoop != nullptr) { KJ_IF_MAYBE(e, threadLocalEventLoop->executor) { maybeSelfExecutor = **e; } } KJ_IF_MAYBE(selfExecutor, maybeSelfExecutor) { // If, while waiting for other threads to process our cancellation request, we have // cancellation requests queued back to this thread, we must process them. Otherwise, // we could deadlock with two threads waiting on each other to process cancellations. // // We don't have a terribly good way to detect this, except to check if the remote // thread is itself waiting for cancellations and, if so, wake ourselves up to check for // cancellations to process. This will busy-loop but at least it should eventually // resolve assuming fair scheduling. // // To make things extra-annoying, in order to update our waitingForCancel flag, we have // to lock our own executor state, but we can't take both locks at once, so we have to // release the other lock in the meantime. // Make sure we unset waitingForCancel on the way out. KJ_DEFER({ lock = {}; Vector<_::XThreadEvent*> eventsToCancelOutsideLock; KJ_DEFER(selfExecutor->impl->processAsyncCancellations(eventsToCancelOutsideLock)); auto selfLock = selfExecutor->impl->state.lockExclusive(); selfLock->waitingForCancel = false; selfLock->dispatchCancels(eventsToCancelOutsideLock); // We don't need to re-take the lock on the other executor here; it's not used again // after this scope. }); while (state != DONE) { bool otherThreadIsWaiting = lock->waitingForCancel; // Make sure our waitingForCancel is on and dispatch any pending cancellations on this // thread. lock = {}; { Vector<_::XThreadEvent*> eventsToCancelOutsideLock; KJ_DEFER(selfExecutor->impl->processAsyncCancellations(eventsToCancelOutsideLock)); auto selfLock = selfExecutor->impl->state.lockExclusive(); selfLock->waitingForCancel = true; // Note that we don't have to proactively delete the PromiseNodes extracted from // the canceled events because those nodes belong to this thread and can't possibly // continue executing while we're blocked here. selfLock->dispatchCancels(eventsToCancelOutsideLock); } if (otherThreadIsWaiting) { // We know the other thread was waiting for cancellations to complete a moment ago. // We may have just processed the necessary cancellations in this thread, in which // case the other thread needs a chance to receive control and notice this. Or, it // may be that the other thread is waiting for some third thread to take action. // Either way, we should yield control here to give things a chance to settle. // Otherwise we could end up in a tight busy loop. #if _WIN32 Sleep(0); #else sched_yield(); #endif } // OK now we can take the original lock again. lock = targetExecutor->impl->state.lockExclusive(); // OK, now we can wait for the other thread to either process our cancellation or // indicate that it is waiting for remote cancellation. lock.wait([&](const Executor::Impl::State& executorState) { return state == DONE || executorState.waitingForCancel; }); } } else { // We have no executor of our own so we don't have to worry about cancellation cycles // causing deadlock. // // NOTE: I don't think we can actually get here, because it implies that this is a // synchronous execution, which means there's no way to cancel it. lock.wait([&](auto&) { return state == DONE; }); } KJ_DASSERT(!targetLink.isLinked()); break; } case CANCELING: KJ_FAIL_ASSERT("impossible state: CANCELING should only be set within the above case"); case DONE: // Became done while we waited for lock. Nothing to do. break; } } KJ_IF_MAYBE(e, replyExecutor) { // Since we know we reached the DONE state (or never left UNUSED), we know that the remote // thread is all done playing with our `replyPrev` pointer. Only the current thread could // possibly modify it after this point. So we can skip the lock if it's already null. if (replyLink.isLinked()) { auto lock = e->impl->state.lockExclusive(); lock->replies.remove(*this); } } } void XThreadEvent::sendReply() { KJ_IF_MAYBE(e, replyExecutor) { // Queue the reply. const EventLoop* replyLoop; { auto lock = e->impl->state.lockExclusive(); KJ_IF_MAYBE(l, lock->loop) { lock->replies.add(*this); replyLoop = l; } else { // Calling thread exited without cancelling the promise. This is UB. In fact, // `replyExecutor` is probably already destroyed and we are in use-after-free territory // already. Better abort. KJ_LOG(FATAL, "the thread which called kj::Executor::executeAsync() apparently exited its own " "event loop without canceling the cross-thread promise first; this is undefined " "behavior so I will crash now"); abort(); } } // Note that it's safe to assume `replyLoop` still exists even though we dropped the lock // because that thread would have had to cancel any promises before destroying its own // EventLoop, and when it tries to destroy this promise, it will wait for `state` to become // `DONE`, which we don't set until later on. That's nice because wake() probably makes a // syscall and we'd rather not hold the lock through syscalls. KJ_IF_MAYBE(p, replyLoop->port) { p->wake(); } } } void XThreadEvent::done() { KJ_ASSERT(targetExecutor.get() == ¤tEventLoop().getExecutor(), "calling done() from wrong thread?"); sendReply(); { auto lock = targetExecutor->impl->state.lockExclusive(); switch (state) { case EXECUTING: lock->executing.remove(*this); break; case CANCELING: // Sending thread requested cancellation, but we're done anyway, so it doesn't matter at this // point. lock->cancel.remove(*this); break; default: KJ_FAIL_ASSERT("can't call done() from this state", (uint)state); } setDoneState(); } } inline void XThreadEvent::setDoneState() { __atomic_store_n(&state, DONE, __ATOMIC_RELEASE); } void XThreadEvent::setDisconnected() { result.addException(KJ_EXCEPTION(DISCONNECTED, "Executor's event loop exited before cross-thread event could complete")); } class XThreadEvent::DelayedDoneHack: public Disposer { // Crazy hack: In fire(), we want to call done() if the event is finished. But done() signals // the requesting thread to wake up and possibly delete the XThreadEvent. But the caller (the // EventLoop) still has to set `event->firing = false` after `fire()` returns, so this would be // a race condition use-after-free. // // It just so happens, though, that fire() is allowed to return an optional `Own` to drop, // and the caller drops that pointer immediately after setting event->firing = false. So we // return a pointer whose disposer calls done(). // // It's not quite as much of a hack as it seems: The whole reason fire() returns an Own is // so that the event can delete itself, but do so after the caller sets event->firing = false. // It just happens to be that in this case, the event isn't deleting itself, but rather releasing // itself back to the other thread. protected: void disposeImpl(void* pointer) const override { reinterpret_cast(pointer)->done(); } }; Maybe> XThreadEvent::fire() { static constexpr DelayedDoneHack DISPOSER {}; KJ_IF_MAYBE(n, promiseNode) { n->get()->get(result); promiseNode = nullptr; // make sure to destroy in the thread that created it return Own(this, DISPOSER); } else { KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { promiseNode = execute(); })) { result.addException(kj::mv(*exception)); }; KJ_IF_MAYBE(n, promiseNode) { n->get()->onReady(this); } else { return Own(this, DISPOSER); } } return nullptr; } void XThreadEvent::traceEvent(TraceBuilder& builder) { KJ_IF_MAYBE(n, promiseNode) { n->get()->tracePromise(builder, true); } // We can't safely trace into another thread, so we'll stop here. builder.add(funcTracePtr); } void XThreadEvent::onReady(Event* event) noexcept { onReadyEvent.init(event); } XThreadPaf::XThreadPaf() : state(WAITING), executor(getCurrentThreadExecutor()) {} XThreadPaf::~XThreadPaf() noexcept(false) {} void XThreadPaf::destroy() { auto oldState = WAITING; if (__atomic_load_n(&state, __ATOMIC_ACQUIRE) == DISPATCHED) { // Common case: Promise was fully fulfilled and dispatched, no need for locking. delete this; } else if (__atomic_compare_exchange_n(&state, &oldState, CANCELED, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { // State transitioned from WAITING to CANCELED, so now it's the fulfiller's job to destroy the // object. } else { // Whoops, another thread is already in the process of fulfilling this promise. We'll have to // wait for it to finish and transition the state to FULFILLED. executor.impl->state.when([&](auto&) { return state == FULFILLED || state == DISPATCHED; }, [&](Executor::Impl::State& exState) { if (state == FULFILLED) { // The object is on the queue but was not yet dispatched. Remove it. exState.fulfilled.remove(*this); } }); // It's ours now, delete it. delete this; } } void XThreadPaf::onReady(Event* event) noexcept { onReadyEvent.init(event); } void XThreadPaf::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // We can't safely trace into another thread, so we'll stop here. // Maybe returning the address of get() will give us a function name with meaningful type // information. builder.add(getMethodStartAddress(implicitCast(*this), &PromiseNode::get)); } XThreadPaf::FulfillScope::FulfillScope(XThreadPaf** pointer) { obj = __atomic_exchange_n(pointer, static_cast(nullptr), __ATOMIC_ACQUIRE); auto oldState = WAITING; if (obj == nullptr) { // Already fulfilled (possibly by another thread). } else if (__atomic_compare_exchange_n(&obj->state, &oldState, FULFILLING, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { // Transitioned to FULFILLING, good. } else { // The waiting thread must have canceled. KJ_ASSERT(oldState == CANCELED); // It's our responsibility to clean up, then. delete obj; // Set `obj` null so that we don't try to fill it in or delete it later. obj = nullptr; } } XThreadPaf::FulfillScope::~FulfillScope() noexcept(false) { if (obj != nullptr) { auto lock = obj->executor.impl->state.lockExclusive(); KJ_IF_MAYBE(l, lock->loop) { lock->fulfilled.add(*obj); __atomic_store_n(&obj->state, FULFILLED, __ATOMIC_RELEASE); KJ_IF_MAYBE(p, l->port) { // TODO(perf): It's annoying we have to call wake() with the lock held, but we have to // prevent the destination EventLoop from being destroyed first. p->wake(); } } else { KJ_LOG(FATAL, "the thread which called kj::newPromiseAndCrossThreadFulfiller() apparently exited " "its own event loop without canceling the cross-thread promise first; this is " "undefined behavior so I will crash now"); abort(); } } } kj::Exception XThreadPaf::unfulfilledException() { // TODO(cleanup): Share code with regular PromiseAndFulfiller for stack tracing here. return kj::Exception(kj::Exception::Type::FAILED, __FILE__, __LINE__, kj::heapString( "cross-thread PromiseFulfiller was destroyed without fulfilling the promise.")); } class ExecutorImpl: public Executor, public AtomicRefcounted { public: using Executor::Executor; kj::Own addRef() const override { return kj::atomicAddRef(*this); } }; } // namespace _ Executor::Executor(EventLoop& loop, Badge): impl(kj::heap(loop)) {} Executor::~Executor() noexcept(false) {} bool Executor::isLive() const { return impl->state.lockShared()->loop != nullptr; } void Executor::send(_::XThreadEvent& event, bool sync) const { KJ_ASSERT(event.state == _::XThreadEvent::UNUSED); if (sync) { EventLoop* thisThread = threadLocalEventLoop; if (thisThread != nullptr && thisThread->executor.map([this](auto& e) { return e == this; }).orDefault(false)) { // Invoking a sync request on our own thread. Just execute it directly; if we try to queue // it to the loop, we'll deadlock. auto promiseNode = event.execute(); // If the function returns a promise, we have no way to pump the event loop to wait for it, // because the event loop may already be pumping somewhere up the stack. KJ_ASSERT(promiseNode == nullptr, "can't call executeSync() on own thread's executor with a promise-returning function"); return; } } else { event.replyExecutor = getCurrentThreadExecutor(); // Note that async requests will "just work" even if the target executor is our own thread's // executor. In theory we could detect this case to avoid some locking and signals but that // would be extra code complexity for probably little benefit. } auto lock = impl->state.lockExclusive(); const EventLoop* loop; KJ_IF_MAYBE(l, lock->loop) { loop = l; } else { event.setDisconnected(); return; } event.state = _::XThreadEvent::QUEUED; lock->start.add(event); KJ_IF_MAYBE(p, loop->port) { p->wake(); } else { // Event loop will be waiting on executor.wait(), which will be woken when we unlock the mutex. } if (sync) { lock.wait([&](auto&) { return event.state == _::XThreadEvent::DONE; }); } } void Executor::wait() { Vector<_::XThreadEvent*> eventsToCancelOutsideLock; KJ_DEFER(impl->processAsyncCancellations(eventsToCancelOutsideLock)); auto lock = impl->state.lockExclusive(); lock.wait([](const Impl::State& state) { return state.isDispatchNeeded(); }); lock->dispatchAll(eventsToCancelOutsideLock); } bool Executor::poll() { Vector<_::XThreadEvent*> eventsToCancelOutsideLock; KJ_DEFER(impl->processAsyncCancellations(eventsToCancelOutsideLock)); auto lock = impl->state.lockExclusive(); if (lock->isDispatchNeeded()) { lock->dispatchAll(eventsToCancelOutsideLock); return true; } else { return false; } } EventLoop& Executor::getLoop() const { KJ_IF_MAYBE(l, impl->state.lockShared()->loop) { return *l; } else { kj::throwFatalException(KJ_EXCEPTION(DISCONNECTED, "Executor's event loop has exited")); } } const Executor& getCurrentThreadExecutor() { return currentEventLoop().getExecutor(); } // ======================================================================================= // Fiber implementation. namespace _ { // private #if KJ_USE_FIBERS #if !(_WIN32 || __CYGWIN__) struct FiberStack::Impl { // This struct serves two purposes: // - It contains OS-specific state that we don't want to declare in the header. // - It is allocated at the top of the fiber's stack area, so the Impl pointer also serves to // track where the stack was allocated. jmp_buf fiberJmpBuf; jmp_buf originalJmpBuf; #if KJ_HAS_COMPILER_FEATURE(address_sanitizer) // Stuff that we need to pass to __sanitizer_start_switch_fiber() / // __sanitizer_finish_switch_fiber() when using ASAN. void* originalFakeStack = nullptr; void* fiberFakeStack = nullptr; // Pointer to ASAN "fake stack" associated with the fiber and its calling stack. Filled in by // __sanitizer_start_switch_fiber() before switching away, consumed by // __sanitizer_finish_switch_fiber() upon switching back. void const* originalBottom; size_t originalSize; // Size and location of the original stack before switching fibers. These are filled in by // __sanitizer_finish_switch_fiber() after the switch, and must be passed to // __sanitizer_start_switch_fiber() when switching back later. #endif static Impl* alloc(size_t stackSize, ucontext_t* context) { #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif size_t pageSize = getPageSize(); size_t allocSize = stackSize + pageSize; // size plus guard page and impl // Allocate virtual address space for the stack but make it inaccessible initially. // TODO(someday): Does it make sense to use MAP_GROWSDOWN on Linux? It's a kind of bizarre flag // that causes the mapping to automatically allocate extra pages (beyond the range specified) // until it hits something... Note that on FreeBSD, MAP_STACK has the effect that // MAP_GROWSDOWN has on Linux. (MAP_STACK, meanwhile, has no effect on Linux.) void* stackMapping = mmap(nullptr, allocSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (stackMapping == MAP_FAILED) { KJ_FAIL_SYSCALL("mmap(new stack)", errno); } KJ_ON_SCOPE_FAILURE({ KJ_SYSCALL(munmap(stackMapping, allocSize)) { break; } }); void* stack = reinterpret_cast(stackMapping) + pageSize; // Now mark everything except the guard page as read-write. We assume the stack grows down, so // the guard page is at the beginning. No modern architecture uses stacks that grow up. KJ_SYSCALL(mprotect(stack, stackSize, PROT_READ | PROT_WRITE)); // Stick `Impl` at the top of the stack. Impl* impl = (reinterpret_cast(reinterpret_cast(stack) + stackSize) - 1); // Note: mmap() allocates zero'd pages so we don't have to memset() anything here. KJ_SYSCALL(getcontext(context)); #if __APPLE__ && __aarch64__ // Per issue #1386, apple on arm64 zeros the entire configured stack. // But this is redundant, since we just allocated the stack with mmap() which // returns zero'd pages. Re-zeroing is both slow and results in prematurely // allocating pages we may not need -- it's normal for stacks to rely heavily // on lazy page allocation to avoid wasting memory. Instead, we lie: // we allocate the full size, but tell the ucontext the stack is the last // page only. This appears to work as no particular bounds checks or // anything are set up based on what we say here. context->uc_stack.ss_size = min(pageSize, stackSize) - sizeof(Impl); context->uc_stack.ss_sp = reinterpret_cast(stack) + stackSize - min(pageSize, stackSize); #else context->uc_stack.ss_size = stackSize - sizeof(Impl); context->uc_stack.ss_sp = reinterpret_cast(stack); #endif context->uc_stack.ss_flags = 0; // We don't use uc_link since our fiber start routine runs forever in a loop to allow for // reuse. When we're done with the fiber, we just destroy it, without switching to it's // stack. This is safe since the start routine doesn't allocate any memory or RAII objects // before looping. context->uc_link = 0; return impl; } static void free(Impl* impl, size_t stackSize) { size_t allocSize = stackSize + getPageSize(); void* stack = reinterpret_cast(impl + 1) - allocSize; KJ_SYSCALL(munmap(stack, allocSize)) { break; } } static size_t getPageSize() { #ifndef _SC_PAGESIZE #define _SC_PAGESIZE _SC_PAGE_SIZE #endif static size_t result = sysconf(_SC_PAGESIZE); return result; } }; #endif #endif struct FiberStack::StartRoutine { #if _WIN32 || __CYGWIN__ static void WINAPI run(LPVOID ptr) { // This is the static C-style function we pass to CreateFiber(). reinterpret_cast(ptr)->run(); } #else [[noreturn]] static void run(int arg1, int arg2) { // This is the static C-style function we pass to makeContext(). // POSIX says the arguments are ints, not pointers. So we split our pointer in half in order to // work correctly on 64-bit machines. Gross. uintptr_t ptr = static_cast(arg1); ptr |= static_cast(static_cast(arg2)) << (sizeof(ptr) * 4); auto& stack = *reinterpret_cast(ptr); __sanitizer_finish_switch_fiber(nullptr, &stack.impl->originalBottom, &stack.impl->originalSize); // We first switch to the fiber inside of the FiberStack constructor. This is just for // initialization purposes, and we're expected to switch back immediately. stack.switchToMain(); // OK now have a real job. stack.run(); } #endif }; void FiberStack::run() { // Loop forever so that the fiber can be reused. for (;;) { KJ_SWITCH_ONEOF(main) { KJ_CASE_ONEOF(event, FiberBase*) { event->run(); } KJ_CASE_ONEOF(func, SynchronousFunc*) { KJ_IF_MAYBE(exception, kj::runCatchingExceptions(func->func)) { func->exception.emplace(kj::mv(*exception)); } } } // Wait for the fiber to be used again. Note the fiber might simply be destroyed without this // ever returning. That's OK because we don't have any nontrivial destructors on the stack // at this point. switchToMain(); } } FiberStack::FiberStack(size_t stackSizeParam) // Force stackSize to a reasonable minimum. : stackSize(kj::max(stackSizeParam, 65536)) { #if KJ_USE_FIBERS #if _WIN32 || __CYGWIN__ // We can create fibers before we convert the main thread into a fiber in FiberBase KJ_WIN32(osFiber = CreateFiber(stackSize, &StartRoutine::run, this)); #else // Note: Nothing below here can throw. If that changes then we need to call Impl::free(impl) // on exceptions... ucontext_t context; impl = Impl::alloc(stackSize, &context); // POSIX says the arguments are ints, not pointers. So we split our pointer in half in order to // work correctly on 64-bit machines. Gross. uintptr_t ptr = reinterpret_cast(this); int arg1 = ptr & ((uintptr_t(1) << (sizeof(ptr) * 4)) - 1); int arg2 = ptr >> (sizeof(ptr) * 4); makecontext(&context, reinterpret_cast(&StartRoutine::run), 2, arg1, arg2); __sanitizer_start_switch_fiber(&impl->originalFakeStack, impl, stackSize - sizeof(Impl)); if (_setjmp(impl->originalJmpBuf) == 0) { setcontext(&context); } __sanitizer_finish_switch_fiber(impl->originalFakeStack, nullptr, nullptr); #endif #else #if KJ_NO_EXCEPTIONS KJ_UNIMPLEMENTED("Fibers are not implemented because exceptions are disabled"); #else KJ_UNIMPLEMENTED( "Fibers are not implemented on this platform because its C library lacks setcontext() " "and friends. If you'd like to see fiber support added, file a bug to let us know. " "We can likely make it happen using assembly, but didn't want to try unless it was " "actually needed."); #endif #endif } FiberStack::~FiberStack() noexcept(false) { #if KJ_USE_FIBERS #if _WIN32 || __CYGWIN__ DeleteFiber(osFiber); #else Impl::free(impl, stackSize); #endif #endif } void FiberStack::initialize(FiberBase& fiber) { KJ_REQUIRE(this->main == nullptr); this->main = &fiber; } void FiberStack::initialize(SynchronousFunc& func) { KJ_REQUIRE(this->main == nullptr); this->main = &func; } FiberBase::FiberBase(size_t stackSize, _::ExceptionOrValue& result, SourceLocation location) : Event(location), state(WAITING), stack(kj::heap(stackSize)), result(result) { stack->initialize(*this); ensureThreadCanRunFibers(); } FiberBase::FiberBase(const FiberPool& pool, _::ExceptionOrValue& result, SourceLocation location) : Event(location), state(WAITING), result(result) { stack = pool.impl->takeStack(); stack->initialize(*this); ensureThreadCanRunFibers(); } FiberBase::~FiberBase() noexcept(false) {} void FiberBase::cancel() { // Called by `~Fiber()` to begin teardown. We can't do this work in `~FiberBase()` because the // `Fiber` subclass contains members that may still be in-use until the fiber stops. switch (state) { case WAITING: // We can't just free the stack while the fiber is running. We need to force it to execute // until finished, so we cause it to throw an exception. state = CANCELED; stack->switchToFiber(); // The fiber should only switch back to the main stack on completion, because any further // calls to wait() would throw before trying to switch. KJ_ASSERT(state == FINISHED); // The fiber shut down properly so the stack is safe to reuse. stack->reset(); break; case RUNNING: case CANCELED: // Bad news. KJ_LOG(FATAL, "fiber tried to cancel itself"); ::abort(); break; case FINISHED: // Normal completion, yay. stack->reset(); break; } } Maybe> FiberBase::fire() { KJ_ASSERT(state == WAITING); state = RUNNING; stack->switchToFiber(); return nullptr; } void FiberStack::switchToFiber() { // Switch from the main stack to the fiber. Returns once the fiber either calls switchToMain() // or returns from its main function. #if KJ_USE_FIBERS #if _WIN32 || __CYGWIN__ SwitchToFiber(osFiber); #else __sanitizer_start_switch_fiber(&impl->originalFakeStack, impl, stackSize - sizeof(Impl)); if (_setjmp(impl->originalJmpBuf) == 0) { _longjmp(impl->fiberJmpBuf, 1); } __sanitizer_finish_switch_fiber(impl->originalFakeStack, nullptr, nullptr); #endif #endif } void FiberStack::switchToMain() { // Switch from the fiber to the main stack. Returns the next time the main stack calls // switchToFiber(). #if KJ_USE_FIBERS #if _WIN32 || __CYGWIN__ SwitchToFiber(getMainWin32Fiber()); #else // TODO(someady): In theory, the last time we switch away from the fiber, we should pass `nullptr` // for the first argument here, so that ASAN destroys the fake stack. However, as currently // designed, we don't actually know if we're switching away for the last time. It's understood // that when we call switchToMain() in FiberStack::run(), then the main stack is allowed to // destroy the fiber, or reuse it. I don't want to develop a mechanism to switch back to the // fiber on final destruction just to get the hints right, so instead we leak the fake stack. // This doesn't seem to cause any problems -- it's not even detected by ASAN as a memory leak. // But if we wanted to run ASAN builds in production or something, it might be an issue. __sanitizer_start_switch_fiber(&impl->fiberFakeStack, impl->originalBottom, impl->originalSize); if (_setjmp(impl->fiberJmpBuf) == 0) { _longjmp(impl->originalJmpBuf, 1); } __sanitizer_finish_switch_fiber(impl->fiberFakeStack, &impl->originalBottom, &impl->originalSize); #endif #endif } void FiberBase::run() { #if !KJ_NO_EXCEPTIONS bool caughtCanceled = false; state = RUNNING; KJ_DEFER(state = FINISHED); WaitScope waitScope(currentEventLoop(), *this); try { KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { runImpl(waitScope); })) { result.addException(kj::mv(*exception)); } } catch (CanceledException) { if (state != CANCELED) { // no idea who would throw this but it's not really our problem result.addException(KJ_EXCEPTION(FAILED, "Caught CanceledException, but fiber wasn't canceled")); } caughtCanceled = true; } if (state == CANCELED && !caughtCanceled) { KJ_LOG(ERROR, "Canceled fiber apparently caught CanceledException and didn't rethrow it. " "Generally, applications should not catch CanceledException, but if they do, they must always rethrow."); } onReadyEvent.arm(); #endif } void FiberBase::onReady(_::Event* event) noexcept { onReadyEvent.init(event); } void FiberBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { if (stopAtNextEvent) return; currentInner->tracePromise(builder, false); stack->trace(builder); } void FiberBase::traceEvent(TraceBuilder& builder) { currentInner->tracePromise(builder, true); stack->trace(builder); onReadyEvent.traceEvent(builder); } } // namespace _ (private) // ======================================================================================= void EventPort::setRunnable(bool runnable) {} void EventPort::wake() const { kj::throwRecoverableException(KJ_EXCEPTION(UNIMPLEMENTED, "cross-thread wake() not implemented by this EventPort implementation")); } EventLoop::EventLoop() : daemons(kj::heap(_::LoggingErrorHandler::instance)) {} EventLoop::EventLoop(EventPort& port) : port(port), daemons(kj::heap(_::LoggingErrorHandler::instance)) {} EventLoop::~EventLoop() noexcept(false) { // Destroy all "daemon" tasks, noting that their destructors might register more daemon tasks. while (!daemons->isEmpty()) { auto oldDaemons = kj::mv(daemons); daemons = kj::heap(_::LoggingErrorHandler::instance); } daemons = nullptr; KJ_IF_MAYBE(e, executor) { // Cancel all outstanding cross-thread events. e->get()->impl->disconnect(); } // The application _should_ destroy everything using the EventLoop before destroying the // EventLoop itself, so if there are events on the loop, this indicates a memory leak. KJ_REQUIRE(head == nullptr, "EventLoop destroyed with events still in the queue. Memory leak?", head->traceEvent()) { // Unlink all the events and hope that no one ever fires them... _::Event* event = head; while (event != nullptr) { _::Event* next = event->next; event->next = nullptr; event->prev = nullptr; event = next; } break; } KJ_REQUIRE(threadLocalEventLoop != this, "EventLoop destroyed while still current for the thread.") { threadLocalEventLoop = nullptr; break; } } void EventLoop::run(uint maxTurnCount) { running = true; KJ_DEFER(running = false); for (uint i = 0; i < maxTurnCount; i++) { if (!turn()) { break; } } setRunnable(isRunnable()); } bool EventLoop::turn() { _::Event* event = head; if (event == nullptr) { // No events in the queue. return false; } else { head = event->next; if (head != nullptr) { head->prev = &head; } depthFirstInsertPoint = &head; if (breadthFirstInsertPoint == &event->next) { breadthFirstInsertPoint = &head; } if (tail == &event->next) { tail = &head; } event->next = nullptr; event->prev = nullptr; Maybe> eventToDestroy; { event->firing = true; KJ_DEFER(event->firing = false); currentlyFiring = event; KJ_DEFER(currentlyFiring = nullptr); eventToDestroy = event->fire(); } depthFirstInsertPoint = &head; return true; } } bool EventLoop::isRunnable() { return head != nullptr; } const Executor& EventLoop::getExecutor() { KJ_IF_MAYBE(e, executor) { return **e; } else { return *executor.emplace(kj::atomicRefcounted<_::ExecutorImpl>(*this, Badge())); } } void EventLoop::setRunnable(bool runnable) { if (runnable != lastRunnableState) { KJ_IF_MAYBE(p, port) { p->setRunnable(runnable); } lastRunnableState = runnable; } } void EventLoop::enterScope() { KJ_REQUIRE(threadLocalEventLoop == nullptr, "This thread already has an EventLoop."); threadLocalEventLoop = this; } void EventLoop::leaveScope() { KJ_REQUIRE(threadLocalEventLoop == this, "WaitScope destroyed in a different thread than it was created in.") { break; } threadLocalEventLoop = nullptr; } void EventLoop::wait() { KJ_IF_MAYBE(p, port) { if (p->wait()) { // Another thread called wake(). Check for cross-thread events. KJ_IF_MAYBE(e, executor) { e->get()->poll(); } } } else KJ_IF_MAYBE(e, executor) { e->get()->wait(); } else { KJ_FAIL_REQUIRE("Nothing to wait for; this thread would hang forever."); } } void EventLoop::poll() { KJ_IF_MAYBE(p, port) { if (p->poll()) { // Another thread called wake(). Check for cross-thread events. KJ_IF_MAYBE(e, executor) { e->get()->poll(); } } } else KJ_IF_MAYBE(e, executor) { e->get()->poll(); } } uint WaitScope::poll(uint maxTurnCount) { KJ_REQUIRE(&loop == threadLocalEventLoop, "WaitScope not valid for this thread."); KJ_REQUIRE(!loop.running, "poll() is not allowed from within event callbacks."); loop.running = true; KJ_DEFER(loop.running = false); uint turnCount = 0; runOnStackPool([&]() { while (turnCount < maxTurnCount) { if (loop.turn()) { ++turnCount; } else { // No events in the queue. Poll for I/O. loop.poll(); if (!loop.isRunnable()) { // Still no events in the queue. We're done. return; } } } }); return turnCount; } void WaitScope::cancelAllDetached() { KJ_REQUIRE(fiber == nullptr, "can't call cancelAllDetached() on a fiber WaitScope, only top-level"); while (!loop.daemons->isEmpty()) { auto oldDaemons = kj::mv(loop.daemons); loop.daemons = kj::heap(_::LoggingErrorHandler::instance); // Destroying `oldDaemons` could theoretically add new ones. } } namespace _ { // private #if !KJ_NO_EXCEPTIONS static kj::CanceledException fiberCanceledException() { // Construct the exception to throw from wait() when the fiber has been canceled (because the // promise returned by startFiber() was dropped before completion). return kj::CanceledException { }; }; #endif void waitImpl(_::OwnPromiseNode&& node, _::ExceptionOrValue& result, WaitScope& waitScope, SourceLocation location) { EventLoop& loop = waitScope.loop; KJ_REQUIRE(&loop == threadLocalEventLoop, "WaitScope not valid for this thread."); #if !KJ_NO_EXCEPTIONS // we don't support fibers when running without exceptions, so just remove the whole block KJ_IF_MAYBE(fiber, waitScope.fiber) { if (fiber->state == FiberBase::CANCELED) { throw fiberCanceledException(); } KJ_REQUIRE(fiber->state == FiberBase::RUNNING, "This WaitScope can only be used within the fiber that created it."); node->setSelfPointer(&node); node->onReady(fiber); fiber->currentInner = node; KJ_DEFER(fiber->currentInner = nullptr); // Switch to the main stack to run the event loop. fiber->state = FiberBase::WAITING; fiber->stack->switchToMain(); // The main stack switched back to us, meaning either the event we registered with // node->onReady() fired, or we are being canceled by FiberBase's destructor. if (fiber->state == FiberBase::CANCELED) { throw fiberCanceledException(); } KJ_ASSERT(fiber->state == FiberBase::RUNNING); } else { #endif KJ_REQUIRE(!loop.running, "wait() is not allowed from within event callbacks."); RootEvent doneEvent(node, reinterpret_cast(&waitImpl), location); node->setSelfPointer(&node); node->onReady(&doneEvent); loop.running = true; KJ_DEFER(loop.running = false); for (;;) { waitScope.runOnStackPool([&]() { uint counter = 0; while (!doneEvent.fired) { if (!loop.turn()) { // No events in the queue. Wait for callback. return; } else if (++counter > waitScope.busyPollInterval) { // Note: It's intentional that if busyPollInterval is kj::maxValue, we never poll. counter = 0; loop.poll(); } } }); if (doneEvent.fired) { break; } else { loop.wait(); } } loop.setRunnable(loop.isRunnable()); #if !KJ_NO_EXCEPTIONS } #endif waitScope.runOnStackPool([&]() { node->get(result); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { node = nullptr; })) { result.addException(kj::mv(*exception)); } }); } bool pollImpl(_::PromiseNode& node, WaitScope& waitScope, SourceLocation location) { EventLoop& loop = waitScope.loop; KJ_REQUIRE(&loop == threadLocalEventLoop, "WaitScope not valid for this thread."); KJ_REQUIRE(waitScope.fiber == nullptr, "poll() is not supported in fibers."); KJ_REQUIRE(!loop.running, "poll() is not allowed from within event callbacks."); RootEvent doneEvent(&node, reinterpret_cast(&pollImpl), location); node.onReady(&doneEvent); loop.running = true; KJ_DEFER(loop.running = false); waitScope.runOnStackPool([&]() { while (!doneEvent.fired) { if (!loop.turn()) { // No events in the queue. Poll for I/O. loop.poll(); if (!doneEvent.fired && !loop.isRunnable()) { // No progress. Give up. node.onReady(nullptr); loop.setRunnable(false); break; } } } }); if (!doneEvent.fired) { return false; } loop.setRunnable(loop.isRunnable()); return true; } Promise yield() { class YieldPromiseNode final: public _::PromiseNode { public: void destroy() override {} void onReady(_::Event* event) noexcept override { if (event) event->armBreadthFirst(); } void get(_::ExceptionOrValue& output) noexcept override { output.as<_::Void>() = _::Void(); } void tracePromise(_::TraceBuilder& builder, bool stopAtNextEvent) override { builder.add(reinterpret_cast(&kj::evalLater)); } }; static YieldPromiseNode NODE; return _::PromiseNode::to>(OwnPromiseNode(&NODE)); } Promise yieldHarder() { class YieldHarderPromiseNode final: public _::PromiseNode { public: void destroy() override {} void onReady(_::Event* event) noexcept override { if (event) event->armLast(); } void get(_::ExceptionOrValue& output) noexcept override { output.as<_::Void>() = _::Void(); } void tracePromise(_::TraceBuilder& builder, bool stopAtNextEvent) override { builder.add(reinterpret_cast(&kj::evalLast)); } }; static YieldHarderPromiseNode NODE; return _::PromiseNode::to>(OwnPromiseNode(&NODE)); } OwnPromiseNode readyNow() { class ReadyNowPromiseNode: public ImmediatePromiseNodeBase { // This is like `ConstPromiseNode`, but the compiler won't let me pass a literal // value of type `Void` as a template parameter. (Might require C++20?) public: void destroy() override {} void get(ExceptionOrValue& output) noexcept override { output.as() = Void(); } }; static ReadyNowPromiseNode NODE; return OwnPromiseNode(&NODE); } OwnPromiseNode neverDone() { class NeverDonePromiseNode final: public _::PromiseNode { public: void destroy() override {} void onReady(_::Event* event) noexcept override { // ignore } void get(_::ExceptionOrValue& output) noexcept override { KJ_FAIL_REQUIRE("Not ready."); } void tracePromise(_::TraceBuilder& builder, bool stopAtNextEvent) override { builder.add(_::getMethodStartAddress(kj::NEVER_DONE, &_::NeverDone::wait)); } }; static NeverDonePromiseNode NODE; return OwnPromiseNode(&NODE); } void NeverDone::wait(WaitScope& waitScope, SourceLocation location) const { ExceptionOr dummy; waitImpl(neverDone(), dummy, waitScope, location); KJ_UNREACHABLE; } void detach(kj::Promise&& promise) { EventLoop& loop = currentEventLoop(); KJ_REQUIRE(loop.daemons.get() != nullptr, "EventLoop is shutting down.") { return; } loop.daemons->add(kj::mv(promise)); } Event::Event(SourceLocation location) : loop(currentEventLoop()), next(nullptr), prev(nullptr), location(location) {} Event::Event(kj::EventLoop& loop, SourceLocation location) : loop(loop), next(nullptr), prev(nullptr), location(location) {} Event::~Event() noexcept(false) { live = 0; // Prevent compiler from eliding this store above. This line probably isn't needed because there // are complex calls later in this destructor, and the compiler probably can't prove that they // won't come back and examine `live`, so it won't elide the write anyway. However, an // atomic_signal_fence is also sufficient to tell the compiler that a signal handler might access // `live`, so it won't optimize away the write. Note that a signal fence does not produce // any instructions, it just blocks compiler optimizations. std::atomic_signal_fence(std::memory_order_acq_rel); disarm(); KJ_REQUIRE(!firing, "Promise callback destroyed itself."); } void Event::armDepthFirst() { KJ_REQUIRE(threadLocalEventLoop == &loop || threadLocalEventLoop == nullptr, "Event armed from different thread than it was created in. You must use " "Executor to queue events cross-thread."); if (live != MAGIC_LIVE_VALUE) { ([this]() noexcept { KJ_FAIL_ASSERT("tried to arm Event after it was destroyed", location); })(); } if (prev == nullptr) { next = *loop.depthFirstInsertPoint; prev = loop.depthFirstInsertPoint; *prev = this; if (next != nullptr) { next->prev = &next; } loop.depthFirstInsertPoint = &next; if (loop.breadthFirstInsertPoint == prev) { loop.breadthFirstInsertPoint = &next; } if (loop.tail == prev) { loop.tail = &next; } loop.setRunnable(true); } } void Event::armBreadthFirst() { KJ_REQUIRE(threadLocalEventLoop == &loop || threadLocalEventLoop == nullptr, "Event armed from different thread than it was created in. You must use " "Executor to queue events cross-thread."); if (live != MAGIC_LIVE_VALUE) { ([this]() noexcept { KJ_FAIL_ASSERT("tried to arm Event after it was destroyed", location); })(); } if (prev == nullptr) { next = *loop.breadthFirstInsertPoint; prev = loop.breadthFirstInsertPoint; *prev = this; if (next != nullptr) { next->prev = &next; } loop.breadthFirstInsertPoint = &next; if (loop.tail == prev) { loop.tail = &next; } loop.setRunnable(true); } } void Event::armLast() { KJ_REQUIRE(threadLocalEventLoop == &loop || threadLocalEventLoop == nullptr, "Event armed from different thread than it was created in. You must use " "Executor to queue events cross-thread."); if (live != MAGIC_LIVE_VALUE) { ([this]() noexcept { KJ_FAIL_ASSERT("tried to arm Event after it was destroyed", location); })(); } if (prev == nullptr) { next = *loop.breadthFirstInsertPoint; prev = loop.breadthFirstInsertPoint; *prev = this; if (next != nullptr) { next->prev = &next; } // We don't update loop.breadthFirstInsertPoint because we want further inserts to go *before* // this event. if (loop.tail == prev) { loop.tail = &next; } loop.setRunnable(true); } } bool Event::isNext() { return loop.running && loop.head == this; } void Event::disarm() { if (prev != nullptr) { if (threadLocalEventLoop != &loop && threadLocalEventLoop != nullptr) { KJ_LOG(FATAL, "Promise destroyed from a different thread than it was created in."); // There's no way out of this place without UB, so abort now. abort(); } if (loop.tail == &next) { loop.tail = prev; } if (loop.depthFirstInsertPoint == &next) { loop.depthFirstInsertPoint = prev; } if (loop.breadthFirstInsertPoint == &next) { loop.breadthFirstInsertPoint = prev; } *prev = next; if (next != nullptr) { next->prev = prev; } prev = nullptr; next = nullptr; } } String Event::traceEvent() { void* space[32]; TraceBuilder builder(space); traceEvent(builder); return kj::str(builder); } String TraceBuilder::toString() { auto result = finish(); return kj::str(stringifyStackTraceAddresses(result), stringifyStackTrace(result)); } } // namespace _ (private) ArrayPtr getAsyncTrace(ArrayPtr space) { EventLoop* loop = threadLocalEventLoop; if (loop == nullptr) return nullptr; if (loop->currentlyFiring == nullptr) return nullptr; _::TraceBuilder builder(space); loop->currentlyFiring->traceEvent(builder); return builder.finish(); } kj::String getAsyncTrace() { void* space[32]; auto trace = getAsyncTrace(space); return kj::str(stringifyStackTraceAddresses(trace), stringifyStackTrace(trace)); } // ======================================================================================= namespace _ { // private kj::String PromiseBase::trace() { void* space[32]; TraceBuilder builder(space); node->tracePromise(builder, false); return kj::str(builder); } void PromiseNode::setSelfPointer(OwnPromiseNode* selfPtr) noexcept {} void PromiseNode::OnReadyEvent::init(Event* newEvent) { if (event == _kJ_ALREADY_READY) { // A new continuation was added to a promise that was already ready. In this case, we schedule // breadth-first, to make it difficult for applications to accidentally starve the event loop // by repeatedly waiting on immediate promises. if (newEvent) newEvent->armBreadthFirst(); } else { event = newEvent; } } void PromiseNode::OnReadyEvent::arm() { KJ_ASSERT(event != _kJ_ALREADY_READY, "arm() should only be called once"); if (event != nullptr) { // A promise resolved and an event is already waiting on it. In this case, arm in depth-first // order so that the event runs immediately after the current one. This way, chained promises // execute together for better cache locality and lower latency. event->armDepthFirst(); } event = _kJ_ALREADY_READY; } void PromiseNode::OnReadyEvent::armBreadthFirst() { KJ_ASSERT(event != _kJ_ALREADY_READY, "armBreadthFirst() should only be called once"); if (event != nullptr) { // A promise resolved and an event is already waiting on it. event->armBreadthFirst(); } event = _kJ_ALREADY_READY; } // ------------------------------------------------------------------- ImmediatePromiseNodeBase::ImmediatePromiseNodeBase() {} ImmediatePromiseNodeBase::~ImmediatePromiseNodeBase() noexcept(false) {} void ImmediatePromiseNodeBase::onReady(Event* event) noexcept { if (event) event->armBreadthFirst(); } void ImmediatePromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // Maybe returning the address of get() will give us a function name with meaningful type // information. builder.add(getMethodStartAddress(implicitCast(*this), &PromiseNode::get)); } ImmediateBrokenPromiseNode::ImmediateBrokenPromiseNode(Exception&& exception) : exception(kj::mv(exception)) {} void ImmediateBrokenPromiseNode::destroy() { freePromise(this); } void ImmediateBrokenPromiseNode::get(ExceptionOrValue& output) noexcept { output.exception = kj::mv(exception); } // ------------------------------------------------------------------- AttachmentPromiseNodeBase::AttachmentPromiseNodeBase(OwnPromiseNode&& dependencyParam) : dependency(kj::mv(dependencyParam)) { dependency->setSelfPointer(&dependency); } void AttachmentPromiseNodeBase::onReady(Event* event) noexcept { dependency->onReady(event); } void AttachmentPromiseNodeBase::get(ExceptionOrValue& output) noexcept { dependency->get(output); } void AttachmentPromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { dependency->tracePromise(builder, stopAtNextEvent); // TODO(debug): Maybe use __builtin_return_address to get the locations that called fork() and // addBranch()? } void AttachmentPromiseNodeBase::dropDependency() { dependency = nullptr; } // ------------------------------------------------------------------- TransformPromiseNodeBase::TransformPromiseNodeBase( OwnPromiseNode&& dependencyParam, void* continuationTracePtr) : dependency(kj::mv(dependencyParam)), continuationTracePtr(continuationTracePtr) { dependency->setSelfPointer(&dependency); } void TransformPromiseNodeBase::onReady(Event* event) noexcept { dependency->onReady(event); } void TransformPromiseNodeBase::get(ExceptionOrValue& output) noexcept { KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { getImpl(output); dropDependency(); })) { output.addException(kj::mv(*exception)); } } void TransformPromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // Note that we null out the dependency just before calling our own continuation, which // conveniently means that if we're currently executing the continuation when the trace is // requested, it won't trace into the obsolete dependency. Nice. if (dependency.get() != nullptr) { dependency->tracePromise(builder, stopAtNextEvent); } builder.add(continuationTracePtr); } void TransformPromiseNodeBase::dropDependency() { dependency = nullptr; } void TransformPromiseNodeBase::getDepResult(ExceptionOrValue& output) { dependency->get(output); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() { dependency = nullptr; })) { output.addException(kj::mv(*exception)); } KJ_IF_MAYBE(e, output.exception) { e->addTrace(continuationTracePtr); } } // ------------------------------------------------------------------- ForkBranchBase::ForkBranchBase(OwnForkHubBase&& hubParam): hub(kj::mv(hubParam)) { if (hub->tailBranch == nullptr) { onReadyEvent.arm(); } else { // Insert into hub's linked list of branches. prevPtr = hub->tailBranch; *prevPtr = this; next = nullptr; hub->tailBranch = &next; } } ForkBranchBase::~ForkBranchBase() noexcept(false) { if (prevPtr != nullptr) { // Remove from hub's linked list of branches. *prevPtr = next; (next == nullptr ? hub->tailBranch : next->prevPtr) = prevPtr; } } void ForkBranchBase::hubReady() noexcept { onReadyEvent.arm(); } void ForkBranchBase::releaseHub(ExceptionOrValue& output) { KJ_IF_MAYBE(exception, kj::runCatchingExceptions([this]() { hub = nullptr; })) { output.addException(kj::mv(*exception)); } } void ForkBranchBase::onReady(Event* event) noexcept { onReadyEvent.init(event); } void ForkBranchBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { if (stopAtNextEvent) return; if (hub.get() != nullptr) { hub->inner->tracePromise(builder, false); } // TODO(debug): Maybe use __builtin_return_address to get the locations that called fork() and // addBranch()? } // ------------------------------------------------------------------- ForkHubBase::ForkHubBase(OwnPromiseNode&& innerParam, ExceptionOrValue& resultRef, SourceLocation location) : Event(location), inner(kj::mv(innerParam)), resultRef(resultRef) { inner->setSelfPointer(&inner); inner->onReady(this); } Maybe> ForkHubBase::fire() { // Dependency is ready. Fetch its result and then delete the node. inner->get(resultRef); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([this]() { inner = nullptr; })) { resultRef.addException(kj::mv(*exception)); } for (auto branch = headBranch; branch != nullptr; branch = branch->next) { branch->hubReady(); *branch->prevPtr = nullptr; branch->prevPtr = nullptr; } *tailBranch = nullptr; // Indicate that the list is no longer active. tailBranch = nullptr; return nullptr; } void ForkHubBase::traceEvent(TraceBuilder& builder) { if (inner.get() != nullptr) { inner->tracePromise(builder, true); } if (headBranch != nullptr) { // We'll trace down the first branch, I guess. headBranch->onReadyEvent.traceEvent(builder); } } // ------------------------------------------------------------------- ChainPromiseNode::ChainPromiseNode(OwnPromiseNode innerParam, SourceLocation location) : Event(location), state(STEP1), inner(kj::mv(innerParam)) { inner->setSelfPointer(&inner); inner->onReady(this); } ChainPromiseNode::~ChainPromiseNode() noexcept(false) {} void ChainPromiseNode::destroy() { freePromise(this); } void ChainPromiseNode::onReady(Event* event) noexcept { switch (state) { case STEP1: onReadyEvent = event; return; case STEP2: inner->onReady(event); return; } KJ_UNREACHABLE; } void ChainPromiseNode::setSelfPointer(OwnPromiseNode* selfPtr) noexcept { if (state == STEP2) { *selfPtr = kj::mv(inner); // deletes this! selfPtr->get()->setSelfPointer(selfPtr); } else { this->selfPtr = selfPtr; } } void ChainPromiseNode::get(ExceptionOrValue& output) noexcept { KJ_REQUIRE(state == STEP2); return inner->get(output); } void ChainPromiseNode::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { if (stopAtNextEvent && state == STEP1) { // In STEP1, we are an Event -- when the inner node resolves, it will arm *this* object. // In STEP2, we are not an Event -- when the inner node resolves, it directly arms our parent // event. return; } inner->tracePromise(builder, stopAtNextEvent); } Maybe> ChainPromiseNode::fire() { KJ_REQUIRE(state != STEP2); static_assert(sizeof(Promise) == sizeof(PromiseBase), "This code assumes Promise does not add any new members to PromiseBase."); ExceptionOr intermediate; inner->get(intermediate); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([this]() { inner = nullptr; })) { intermediate.addException(kj::mv(*exception)); } KJ_IF_MAYBE(exception, intermediate.exception) { // There is an exception. If there is also a value, delete it. kj::runCatchingExceptions([&]() { intermediate.value = nullptr; }); // Now set step2 to a rejected promise. inner = allocPromise(kj::mv(*exception)); } else KJ_IF_MAYBE(value, intermediate.value) { // There is a value and no exception. The value is itself a promise. Adopt it as our // step2. inner = _::PromiseNode::from(kj::mv(*value)); } else { // We can only get here if inner->get() returned neither an exception nor a // value, which never actually happens. KJ_FAIL_ASSERT("Inner node returned empty value."); } state = STEP2; if (selfPtr != nullptr) { // Hey, we can shorten the chain here. auto chain = selfPtr->downcast(); *selfPtr = kj::mv(inner); selfPtr->get()->setSelfPointer(selfPtr); if (onReadyEvent != nullptr) { selfPtr->get()->onReady(onReadyEvent); } // Return our self-pointer so that the caller takes care of deleting it. return Own(kj::Own(kj::mv(chain))); } else { inner->setSelfPointer(&inner); if (onReadyEvent != nullptr) { inner->onReady(onReadyEvent); } return nullptr; } } void ChainPromiseNode::traceEvent(TraceBuilder& builder) { switch (state) { case STEP1: if (inner.get() != nullptr) { inner->tracePromise(builder, true); } if (!builder.full() && onReadyEvent != nullptr) { onReadyEvent->traceEvent(builder); } break; case STEP2: // This probably never happens -- a trace being generated after the meat of fire() already // executed. If it does, though, we probably can't do anything here. We don't know if // `onReadyEvent` is still valid because we passed it on to the phase-2 promise, and tracing // just `inner` would probably be confusing. Let's just do nothing. break; } } // ------------------------------------------------------------------- ExclusiveJoinPromiseNode::ExclusiveJoinPromiseNode( OwnPromiseNode left, OwnPromiseNode right, SourceLocation location) : left(*this, kj::mv(left), location), right(*this, kj::mv(right), location) {} ExclusiveJoinPromiseNode::~ExclusiveJoinPromiseNode() noexcept(false) {} void ExclusiveJoinPromiseNode::destroy() { freePromise(this); } void ExclusiveJoinPromiseNode::onReady(Event* event) noexcept { onReadyEvent.init(event); } void ExclusiveJoinPromiseNode::get(ExceptionOrValue& output) noexcept { KJ_REQUIRE(left.get(output) || right.get(output), "get() called before ready."); } void ExclusiveJoinPromiseNode::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // TODO(debug): Maybe use __builtin_return_address to get the locations that called // exclusiveJoin()? if (stopAtNextEvent) return; // Trace the left branch I guess. if (left.dependency.get() != nullptr) { left.dependency->tracePromise(builder, false); } else if (right.dependency.get() != nullptr) { right.dependency->tracePromise(builder, false); } } ExclusiveJoinPromiseNode::Branch::Branch( ExclusiveJoinPromiseNode& joinNode, OwnPromiseNode dependencyParam, SourceLocation location) : Event(location), joinNode(joinNode), dependency(kj::mv(dependencyParam)) { dependency->setSelfPointer(&dependency); dependency->onReady(this); } ExclusiveJoinPromiseNode::Branch::~Branch() noexcept(false) {} bool ExclusiveJoinPromiseNode::Branch::get(ExceptionOrValue& output) { if (dependency) { dependency->get(output); return true; } else { return false; } } Maybe> ExclusiveJoinPromiseNode::Branch::fire() { if (dependency) { // Cancel the branch that didn't return first. Ignore exceptions caused by cancellation. if (this == &joinNode.left) { kj::runCatchingExceptions([&]() { joinNode.right.dependency = nullptr; }); } else { kj::runCatchingExceptions([&]() { joinNode.left.dependency = nullptr; }); } joinNode.onReadyEvent.arm(); } else { // The other branch already fired, and this branch was canceled. It's possible for both // branches to fire if both were armed simultaneously. } return nullptr; } void ExclusiveJoinPromiseNode::Branch::traceEvent(TraceBuilder& builder) { if (dependency.get() != nullptr) { dependency->tracePromise(builder, true); } joinNode.onReadyEvent.traceEvent(builder); } // ------------------------------------------------------------------- ArrayJoinPromiseNodeBase::ArrayJoinPromiseNodeBase( Array promises, ExceptionOrValue* resultParts, size_t partSize, SourceLocation location, ArrayJoinBehavior joinBehavior) : joinBehavior(joinBehavior), countLeft(promises.size()) { // Make the branches. auto builder = heapArrayBuilder(promises.size()); for (uint i: indices(promises)) { ExceptionOrValue& output = *reinterpret_cast( reinterpret_cast(resultParts) + i * partSize); builder.add(*this, kj::mv(promises[i]), output, location); } branches = builder.finish(); if (branches.size() == 0) { onReadyEvent.arm(); } } ArrayJoinPromiseNodeBase::~ArrayJoinPromiseNodeBase() noexcept(false) {} void ArrayJoinPromiseNodeBase::onReady(Event* event) noexcept { onReadyEvent.init(event); } void ArrayJoinPromiseNodeBase::get(ExceptionOrValue& output) noexcept { for (auto& branch: branches) { if (joinBehavior == ArrayJoinBehavior::LAZY) { // This implements `joinPromises()`'s lazy evaluation semantics. branch.dependency->get(branch.output); } // If any of the elements threw exceptions, propagate them. KJ_IF_MAYBE(exception, branch.output.exception) { output.addException(kj::mv(*exception)); } } // We either failed fast, or waited for all promises. KJ_DASSERT(countLeft == 0 || output.exception != nullptr); if (output.exception == nullptr) { // No errors. The template subclass will need to fill in the result. getNoError(output); } } void ArrayJoinPromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // TODO(debug): Maybe use __builtin_return_address to get the locations that called // joinPromises()? if (stopAtNextEvent) return; // Trace the first branch I guess. if (branches != nullptr) { branches[0].dependency->tracePromise(builder, false); } } ArrayJoinPromiseNodeBase::Branch::Branch( ArrayJoinPromiseNodeBase& joinNode, OwnPromiseNode dependencyParam, ExceptionOrValue& output, SourceLocation location) : Event(location), joinNode(joinNode), dependency(kj::mv(dependencyParam)), output(output) { dependency->setSelfPointer(&dependency); dependency->onReady(this); } ArrayJoinPromiseNodeBase::Branch::~Branch() noexcept(false) {} Maybe> ArrayJoinPromiseNodeBase::Branch::fire() { if (--joinNode.countLeft == 0 && !joinNode.armed) { joinNode.onReadyEvent.arm(); joinNode.armed = true; } if (joinNode.joinBehavior == ArrayJoinBehavior::EAGER) { // This implements `joinPromisesFailFast()`'s eager-evaluation semantics. dependency->get(output); if (output.exception != nullptr && !joinNode.armed) { joinNode.onReadyEvent.arm(); joinNode.armed = true; } } return nullptr; } void ArrayJoinPromiseNodeBase::Branch::traceEvent(TraceBuilder& builder) { dependency->tracePromise(builder, true); joinNode.onReadyEvent.traceEvent(builder); } ArrayJoinPromiseNode::ArrayJoinPromiseNode( Array promises, Array> resultParts, SourceLocation location, ArrayJoinBehavior joinBehavior) : ArrayJoinPromiseNodeBase(kj::mv(promises), resultParts.begin(), sizeof(ExceptionOr<_::Void>), location, joinBehavior), resultParts(kj::mv(resultParts)) {} ArrayJoinPromiseNode::~ArrayJoinPromiseNode() {} void ArrayJoinPromiseNode::destroy() { freePromise(this); } void ArrayJoinPromiseNode::getNoError(ExceptionOrValue& output) noexcept { output.as<_::Void>() = _::Void(); } } // namespace _ (private) Promise joinPromises(Array>&& promises, SourceLocation location) { return _::PromiseNode::to>(_::allocPromise<_::ArrayJoinPromiseNode>( KJ_MAP(p, promises) { return _::PromiseNode::from(kj::mv(p)); }, heapArray<_::ExceptionOr<_::Void>>(promises.size()), location, _::ArrayJoinBehavior::LAZY)); } Promise joinPromisesFailFast(Array>&& promises, SourceLocation location) { return _::PromiseNode::to>(_::allocPromise<_::ArrayJoinPromiseNode>( KJ_MAP(p, promises) { return _::PromiseNode::from(kj::mv(p)); }, heapArray<_::ExceptionOr<_::Void>>(promises.size()), location, _::ArrayJoinBehavior::EAGER)); } namespace _ { // (private) // ------------------------------------------------------------------- EagerPromiseNodeBase::EagerPromiseNodeBase( OwnPromiseNode&& dependencyParam, ExceptionOrValue& resultRef, SourceLocation location) : Event(location), dependency(kj::mv(dependencyParam)), resultRef(resultRef) { dependency->setSelfPointer(&dependency); dependency->onReady(this); } void EagerPromiseNodeBase::onReady(Event* event) noexcept { onReadyEvent.init(event); } void EagerPromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // TODO(debug): Maybe use __builtin_return_address to get the locations that called // eagerlyEvaluate()? But note that if a non-null exception handler was passed to it, that // creates a TransformPromiseNode which will report the location anyhow. if (stopAtNextEvent) return; if (dependency.get() != nullptr) { dependency->tracePromise(builder, stopAtNextEvent); } } void EagerPromiseNodeBase::traceEvent(TraceBuilder& builder) { if (dependency.get() != nullptr) { dependency->tracePromise(builder, true); } onReadyEvent.traceEvent(builder); } Maybe> EagerPromiseNodeBase::fire() { dependency->get(resultRef); KJ_IF_MAYBE(exception, kj::runCatchingExceptions([this]() { dependency = nullptr; })) { resultRef.addException(kj::mv(*exception)); } onReadyEvent.arm(); return nullptr; } // ------------------------------------------------------------------- void AdapterPromiseNodeBase::onReady(Event* event) noexcept { onReadyEvent.init(event); } void AdapterPromiseNodeBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { // Maybe returning the address of get() will give us a function name with meaningful type // information. builder.add(getMethodStartAddress(implicitCast(*this), &PromiseNode::get)); } void END_FULFILLER_STACK_START_LISTENER_STACK() {} // Dummy symbol used when reporting how a PromiseFulfiller was destroyed without fulfilling the // promise. We end up combining two stack traces into one and we use this as a separator. void WeakFulfillerBase::disposeImpl(void* pointer) const { if (inner == nullptr) { // Already detached. delete this; } else { if (inner->isWaiting()) { // Let's find out if there's an exception being thrown. If so, we'll use it to reject the // promise. inner->reject(getDestructionReason( reinterpret_cast(&END_FULFILLER_STACK_START_LISTENER_STACK), kj::Exception::Type::FAILED, __FILE__, __LINE__, "PromiseFulfiller was destroyed without fulfilling the promise."_kj)); } inner = nullptr; } } } // namespace _ (private) // ------------------------------------------------------------------- namespace _ { // (private) Promise IdentityFunc>::operator()() const { return READY_NOW; } } // namespace _ (private) // ------------------------------------------------------------------- #if KJ_HAS_COROUTINE namespace _ { // (private) CoroutineBase::CoroutineBase(stdcoro::coroutine_handle<> coroutine, ExceptionOrValue& resultRef, SourceLocation location) : Event(location), coroutine(coroutine), resultRef(resultRef) {} CoroutineBase::~CoroutineBase() noexcept(false) { readMaybe(maybeDisposalResults)->destructorRan = true; } void CoroutineBase::unhandled_exception() { // Pretty self-explanatory, we propagate the exception to the promise which owns us, unless // we're being destroyed, in which case we propagate it back to our disposer. Note that all // unhandled exceptions end up here, not just ones after the first co_await. auto exception = getCaughtExceptionAsKj(); KJ_IF_MAYBE(disposalResults, maybeDisposalResults) { // Exception during coroutine destruction. Only record the first one. if (disposalResults->exception == nullptr) { disposalResults->exception = kj::mv(exception); } } else if (isWaiting()) { // Exception during coroutine execution. resultRef.addException(kj::mv(exception)); scheduleResumption(); } else { // Okay, what could this mean? We've already been fulfilled or rejected, but we aren't being // destroyed yet. The only possibility is that we are unwinding the coroutine frame due to a // successful completion, and something in the frame threw. We can't already be rejected, // because rejecting a coroutine involves throwing, which would have unwound the frame prior // to setting `waiting = false`. // // Since we know we're unwinding due to a successful completion, we also know that whatever // Event we may have armed has not yet fired, because we haven't had a chance to return to // the event loop. // final_suspend() has not been called. #if _MSC_VER && !defined(__clang__) // See comment at `finalSuspendCalled`'s definition. KJ_IASSERT(!finalSuspendCalled); #else KJ_IASSERT(!coroutine.done()); #endif // Since final_suspend() hasn't been called, whatever Event is waiting on us has not fired, // and will see this exception. resultRef.addException(kj::mv(exception)); } } void CoroutineBase::onReady(Event* event) noexcept { onReadyEvent.init(event); } void CoroutineBase::tracePromise(TraceBuilder& builder, bool stopAtNextEvent) { if (stopAtNextEvent) return; KJ_IF_MAYBE(promise, promiseNodeForTrace) { promise->tracePromise(builder, stopAtNextEvent); } // Maybe returning the address of coroutine() will give us a function name with meaningful type // information. (Narrator: It doesn't.) builder.add(GetFunctorStartAddress<>::apply(coroutine)); }; Maybe> CoroutineBase::fire() { // Call Awaiter::await_resume() and proceed with the coroutine. Note that this will not destroy // the coroutine if control flows off the end of it, because we return suspend_always() from // final_suspend(). // // It's tempting to arrange to check for exceptions right now and reject the promise that owns // us without resuming the coroutine, which would save us from throwing an exception when we // already know where it's going. But, we don't really know: unlike in the KJ_NO_EXCEPTIONS // case, the `co_await` might be in a try-catch block, so we have no choice but to resume and // throw later. // // TODO(someday): If we ever support coroutines with -fno-exceptions, we'll need to reject the // enclosing coroutine promise here, if the Awaiter's result is exceptional. promiseNodeForTrace = nullptr; coroutine.resume(); return nullptr; } void CoroutineBase::traceEvent(TraceBuilder& builder) { KJ_IF_MAYBE(promise, promiseNodeForTrace) { promise->tracePromise(builder, true); } // Maybe returning the address of coroutine() will give us a function name with meaningful type // information. (Narrator: It doesn't.) builder.add(GetFunctorStartAddress<>::apply(coroutine)); onReadyEvent.traceEvent(builder); } void CoroutineBase::destroy() { // Called by PromiseDisposer to delete the object. Basically a wrapper around coroutine.destroy() // with some stuff to propagate exceptions appropriately. // Objects in the coroutine frame might throw from their destructors, so unhandled_exception() // will need some way to communicate those exceptions back to us. Separately, we also want // confirmation that our own ~Coroutine() destructor ran. To solve this, we put a // DisposalResults object on the stack and set a pointer to it in the Coroutine object. This // indicates to unhandled_exception() and ~Coroutine() where to store the results of the // destruction operation. DisposalResults disposalResults; maybeDisposalResults = &disposalResults; // Need to save this while `unwindDetector` is still valid. bool shouldRethrow = !unwindDetector.isUnwinding(); do { // Clang's implementation of the Coroutines TS does not destroy the Coroutine object or // deallocate the coroutine frame if a destructor of an object on the frame threw an // exception. This is despite the fact that it delivered the exception to _us_ via // unhandled_exception(). Anyway, it appears we can work around this by running // coroutine.destroy() a second time. // // On Clang, `disposalResults.exception != nullptr` implies `!disposalResults.destructorRan`. // We could optimize out the separate `destructorRan` flag if we verify that other compilers // behave the same way. coroutine.destroy(); } while (!disposalResults.destructorRan); // WARNING: `this` is now a dangling pointer. KJ_IF_MAYBE(exception, disposalResults.exception) { if (shouldRethrow) { kj::throwFatalException(kj::mv(*exception)); } else { // An exception is already unwinding the stack, so throwing this secondary exception would // call std::terminate(). } } } CoroutineBase::AwaiterBase::AwaiterBase(OwnPromiseNode node): node(kj::mv(node)) {} CoroutineBase::AwaiterBase::AwaiterBase(AwaiterBase&&) = default; CoroutineBase::AwaiterBase::~AwaiterBase() noexcept(false) { // Make sure it's safe to generate an async stack trace between now and when the Coroutine is // destroyed. KJ_IF_MAYBE(coroutineEvent, maybeCoroutineEvent) { coroutineEvent->promiseNodeForTrace = nullptr; } unwindDetector.catchExceptionsIfUnwinding([this]() { // No need to check for a moved-from state, node will just ignore the nullification. node = nullptr; }); } void CoroutineBase::AwaiterBase::getImpl(ExceptionOrValue& result, void* awaitedAt) { node->get(result); KJ_IF_MAYBE(exception, result.exception) { // Manually extend the stack trace with the instruction address where the co_await occurred. exception->addTrace(awaitedAt); // Pass kj::maxValue for ignoreCount here so that `throwFatalException()` dosen't try to // extend the stack trace. There's no point in extending the trace beyond the single frame we // added above, as the rest of the trace will always be async framework stuff that no one wants // to see. kj::throwFatalException(kj::mv(*exception), kj::maxValue); } } bool CoroutineBase::AwaiterBase::awaitSuspendImpl(CoroutineBase& coroutineEvent) { node->setSelfPointer(&node); node->onReady(&coroutineEvent); if (coroutineEvent.hasSuspendedAtLeastOnce && coroutineEvent.isNext()) { // The result is immediately ready and this coroutine is running on the event loop's stack, not // a user code stack. Let's cancel our event and immediately resume. It's important that we // don't perform this optimization if this is the first suspension, because our caller may // depend on running code before this promise's continuations fire. coroutineEvent.disarm(); // We can resume ourselves by returning false. This accomplishes the same thing as if we had // returned true from await_ready(). return false; } else { // Otherwise, we must suspend. Store a reference to the promise we're waiting on for tracing // purposes; coroutineEvent.fire() and/or ~Adapter() will null this out. coroutineEvent.promiseNodeForTrace = *node; maybeCoroutineEvent = coroutineEvent; coroutineEvent.hasSuspendedAtLeastOnce = true; return true; } } // --------------------------------------------------------- // Helpers for coCapture() void throwMultipleCoCaptureInvocations() { KJ_FAIL_REQUIRE("Attempted to invoke CaptureForCoroutine functor multiple times"); } } // namespace _ (private) #endif // KJ_HAS_COROUTINE } // namespace kj capnproto-c++-1.1.0/src/kj/list.h0000644000175000017500000001636514712011043017265 0ustar00kentonkenton00000000000000// Copyright (c) 2021 Cloudflare, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "common.h" KJ_BEGIN_HEADER namespace kj { template class ListLink; template T::*link> class ListIterator; namespace _ { // (private) KJ_NORETURN(void throwDoubleAdd()); KJ_NORETURN(void throwRemovedNotPresent()); KJ_NORETURN(void throwRemovedWrongList()); KJ_NORETURN(void throwDestroyedWhileInList()); } // namespace _ (private) template T::*link> class List { // A linked list that does no memory allocation. // // The list contains elements of type T that are allocated elsewhere. An existing object of type // T can be added to the list and removed again without doing any heap allocation. This is // achieved by requiring that T contains a field of type ListLink. A pointer-to-member to // this field is the second parameter to the `List` template. // // kj::List is ideally suited to situations where an object wants to be able to "add itself" to // a list of objects waiting for a notification, with the ability to remove itself early if it // wants to stop waiting. With traditional STL containers, these operations would require memory // allocation. // // Example: // // struct Item { // ListLink link; // // ... other members ... // }; // // kj::List itemList; // // Item foo; // itemList.add(foo); // itemList.remove(foo); // // Note that you MUST manually remove an element from the list before destroying it. ListLinks // do not automatically unlink themselves because this could lead to subtle thread-safety bugs // if the List is guarded by a mutex, and that mutex is not currently locked. Normally, you should // have T's destructor remove it from any lists. You can use `link.isLinked()` to check if the // item is currently in a list. // // kj::List is a doubly-linked list in order to allow O(1) removal of any element given only a // reference to the element. However, it only supports forward iteration. // // When iterating over a kj::List, you can safely remove current element which the iterator // points to without breaking the iteration. However, removing any *other* element could // invalidate the iterator. public: List() = default; KJ_DISALLOW_COPY_AND_MOVE(List); bool empty() const { return head == nullptr; } size_t size() const { return listSize; } void add(T& element) { if ((element.*link).prev != nullptr) _::throwDoubleAdd(); *tail = element; (element.*link).prev = tail; tail = &((element.*link).next); ++listSize; } void addFront(T& element) { if ((element.*link).prev != nullptr) _::throwDoubleAdd(); (element.*link).next = head; (element.*link).prev = &head; KJ_IF_MAYBE(oldHead, head) { (oldHead->*link).prev = &(element.*link).next; } else { tail = &(element.*link).next; } head = element; ++listSize; } void remove(T& element) { if ((element.*link).prev == nullptr) _::throwRemovedNotPresent(); *((element.*link).prev) = (element.*link).next; KJ_IF_MAYBE(n, (element.*link).next) { (n->*link).prev = (element.*link).prev; } else { if (tail != &((element.*link).next)) _::throwRemovedWrongList(); tail = (element.*link).prev; } (element.*link).next = nullptr; (element.*link).prev = nullptr; --listSize; } typedef ListIterator Iterator; typedef ListIterator ConstIterator; Iterator begin() { return Iterator(head); } Iterator end() { return Iterator(nullptr); } ConstIterator begin() const { return ConstIterator(head); } ConstIterator end() const { return ConstIterator(nullptr); } T& front() { return *begin(); } const T& front() const { return *begin(); } private: Maybe head; Maybe* tail = &head; size_t listSize = 0; }; template class ListLink { public: ListLink(): next(nullptr), prev(nullptr) {} ~ListLink() noexcept { // Intentionally `noexcept` because we want to crash if a dangling pointer was left in a list. if (prev != nullptr) _::throwDestroyedWhileInList(); } KJ_DISALLOW_COPY_AND_MOVE(ListLink); bool isLinked() const { return prev != nullptr; } private: Maybe next; Maybe* prev; template U::*link> friend class List; template U::*link> friend class ListIterator; }; template T::*link> class ListIterator { public: ListIterator() = default; MaybeConstT& operator*() { KJ_IREQUIRE(current != nullptr, "tried to dereference end of list"); return *_::readMaybe(current); } const T& operator*() const { KJ_IREQUIRE(current != nullptr, "tried to dereference end of list"); return *_::readMaybe(current); } MaybeConstT* operator->() { KJ_IREQUIRE(current != nullptr, "tried to dereference end of list"); return _::readMaybe(current); } const T* operator->() const { KJ_IREQUIRE(current != nullptr, "tried to dereference end of list"); return _::readMaybe(current); } inline ListIterator& operator++() { current = next; next = current.map([](MaybeConstT& obj) -> kj::Maybe { return (obj.*link).next; }) .orDefault(nullptr); return *this; } inline ListIterator operator++(int) { ListIterator result = *this; ++*this; return result; } inline bool operator==(const ListIterator& other) const { return _::readMaybe(current) == _::readMaybe(other.current); } inline bool operator!=(const ListIterator& other) const { return _::readMaybe(current) != _::readMaybe(other.current); } private: Maybe current; Maybe next; // so that the current item can be removed from the list without invalidating the iterator explicit ListIterator(Maybe start) : current(start), next(start.map([](MaybeConstT& obj) -> kj::Maybe { return (obj.*link).next; }) .orDefault(nullptr)) {} friend class List; }; } // namespace kj KJ_END_HEADER capnproto-c++-1.1.0/src/kj/time.c++0000644000175000017500000002276114712011043017366 0ustar00kentonkenton00000000000000// Copyright (c) 2014 Google Inc. (contributed by Remy Blank ) // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #if _WIN32 #include "win32-api-version.h" #endif #include "time.h" #include "debug.h" #include #if _WIN32 #include #else #include #endif namespace kj { const Clock& nullClock() { class NullClock final: public Clock { public: Date now() const override { return UNIX_EPOCH; } }; static KJ_CONSTEXPR(const) NullClock NULL_CLOCK = NullClock(); return NULL_CLOCK; } #if _WIN32 namespace { static constexpr int64_t WIN32_EPOCH_OFFSET = 116444736000000000ull; // Number of 100ns intervals from Jan 1, 1601 to Jan 1, 1970. static Date toKjDate(FILETIME t) { int64_t value = (static_cast(t.dwHighDateTime) << 32) | t.dwLowDateTime; return (value - WIN32_EPOCH_OFFSET) * (100 * kj::NANOSECONDS) + UNIX_EPOCH; } class Win32CoarseClock: public Clock { public: Date now() const override { FILETIME ft; GetSystemTimeAsFileTime(&ft); return toKjDate(ft); } }; class Win32PreciseClock: public Clock { typedef VOID WINAPI GetSystemTimePreciseAsFileTimeFunc(LPFILETIME); public: Date now() const override { static GetSystemTimePreciseAsFileTimeFunc* const getSystemTimePreciseAsFileTimePtr = getGetSystemTimePreciseAsFileTime(); FILETIME ft; if (getSystemTimePreciseAsFileTimePtr == nullptr) { // We can't use QueryPerformanceCounter() to get any more precision because we have no way // of knowing when the calendar clock jumps. So I guess we're stuck. GetSystemTimeAsFileTime(&ft); } else { getSystemTimePreciseAsFileTimePtr(&ft); } return toKjDate(ft); } private: static GetSystemTimePreciseAsFileTimeFunc* getGetSystemTimePreciseAsFileTime() { // Dynamically look up the function GetSystemTimePreciseAsFileTimeFunc(). This was only // introduced as of Windows 8, so it might be missing. #if __GNUC__ && !__clang__ && __GNUC__ >= 8 // GCC 8 warns that our reinterpret_cast of a function pointer below is casting between // incompatible types. Yes, GCC, we know that. This is the nature of GetProcAddress(); it returns // everything as `long long int (*)()` and we have to cast to the actual type. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif return reinterpret_cast(GetProcAddress( GetModuleHandleA("kernel32.dll"), "GetSystemTimePreciseAsFileTime")); } }; class Win32CoarseMonotonicClock: public MonotonicClock { public: TimePoint now() const override { return kj::origin() + GetTickCount64() * kj::MILLISECONDS; } }; class Win32PreciseMonotonicClock: public MonotonicClock { // Precise clock implemented using QueryPerformanceCounter(). // // TODO(someday): Windows 10 has QueryUnbiasedInterruptTime() and // QueryUnbiasedInterruptTimePrecise(), a new API for monotonic timing that isn't as difficult. // Is there any benefit to dynamically checking for these and using them if available? public: TimePoint now() const override { static const QpcProperties props; LARGE_INTEGER now; QueryPerformanceCounter(&now); uint64_t adjusted = now.QuadPart - props.origin; uint64_t ns = mulDiv64(adjusted, 1'000'000'000, props.frequency); return kj::origin() + ns * kj::NANOSECONDS; } private: struct QpcProperties { uint64_t origin; // What QueryPerformanceCounter() would have returned at the time when GetTickCount64() returned // zero. Used to ensure that the coarse and precise timers return similar values. uint64_t frequency; // From QueryPerformanceFrequency(). QpcProperties() { LARGE_INTEGER now, freqLi; uint64_t ticks = GetTickCount64(); QueryPerformanceCounter(&now); QueryPerformanceFrequency(&freqLi); frequency = freqLi.QuadPart; // Convert the millisecond tick count into performance counter ticks. uint64_t ticksAsQpc = mulDiv64(ticks, freqLi.QuadPart, 1000); origin = now.QuadPart - ticksAsQpc; } }; static inline uint64_t mulDiv64(uint64_t value, uint64_t numer, uint64_t denom) { // Inspired by: // https://github.com/rust-lang/rust/pull/22788/files#diff-24f054cd23f65af3b574c6ce8aa5a837R54 // Computes (value*numer)/denom without overflow, as long as both // (numer*denom) and the overall result fit into 64 bits. uint64_t q = value / denom; uint64_t r = value % denom; return q * numer + r * numer / denom; } }; } // namespace const Clock& systemCoarseCalendarClock() { static constexpr Win32CoarseClock clock; return clock; } const Clock& systemPreciseCalendarClock() { static constexpr Win32PreciseClock clock; return clock; } const MonotonicClock& systemCoarseMonotonicClock() { static constexpr Win32CoarseMonotonicClock clock; return clock; } const MonotonicClock& systemPreciseMonotonicClock() { static constexpr Win32PreciseMonotonicClock clock; return clock; } #else namespace { class PosixClock: public Clock { public: constexpr PosixClock(clockid_t clockId): clockId(clockId) {} Date now() const override { struct timespec ts; KJ_SYSCALL(clock_gettime(clockId, &ts)); return UNIX_EPOCH + ts.tv_sec * kj::SECONDS + ts.tv_nsec * kj::NANOSECONDS; } private: clockid_t clockId; }; class PosixMonotonicClock: public MonotonicClock { public: constexpr PosixMonotonicClock(clockid_t clockId): clockId(clockId) {} TimePoint now() const override { struct timespec ts; KJ_SYSCALL(clock_gettime(clockId, &ts)); return kj::origin() + ts.tv_sec * kj::SECONDS + ts.tv_nsec * kj::NANOSECONDS; } private: clockid_t clockId; }; } // namespace // FreeBSD has "_PRECISE", but Linux just defaults to precise. #ifndef CLOCK_REALTIME_PRECISE #define CLOCK_REALTIME_PRECISE CLOCK_REALTIME #endif #ifndef CLOCK_MONOTONIC_PRECISE #define CLOCK_MONOTONIC_PRECISE CLOCK_MONOTONIC #endif // FreeBSD has "_FAST", Linux has "_COARSE". // MacOS has an "_APPROX" but only for CLOCK_MONOTONIC_RAW, which isn't helpful. #ifndef CLOCK_REALTIME_COARSE #ifdef CLOCK_REALTIME_FAST #define CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST #else #define CLOCK_REALTIME_COARSE CLOCK_REALTIME #endif #endif #ifndef CLOCK_MONOTONIC_COARSE #ifdef CLOCK_MONOTONIC_FAST #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST #else #define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC #endif #endif const Clock& systemCoarseCalendarClock() { static constexpr PosixClock clock(CLOCK_REALTIME_COARSE); return clock; } const Clock& systemPreciseCalendarClock() { static constexpr PosixClock clock(CLOCK_REALTIME_PRECISE); return clock; } const MonotonicClock& systemCoarseMonotonicClock() { static constexpr PosixMonotonicClock clock(CLOCK_MONOTONIC_COARSE); return clock; } const MonotonicClock& systemPreciseMonotonicClock() { static constexpr PosixMonotonicClock clock(CLOCK_MONOTONIC_PRECISE); return clock; } #endif CappedArray KJ_STRINGIFY(TimePoint t) { return kj::toCharSequence(t - kj::origin()); } CappedArray KJ_STRINGIFY(Date d) { return kj::toCharSequence(d - UNIX_EPOCH); } CappedArray KJ_STRINGIFY(Duration d) { bool negative = d < 0 * kj::SECONDS; uint64_t ns = d / kj::NANOSECONDS; if (negative) { ns = -ns; } auto digits = kj::toCharSequence(ns); ArrayPtr arr = digits; size_t point; kj::StringPtr suffix; kj::Duration unit; if (digits.size() > 9) { point = arr.size() - 9; suffix = "s"; unit = kj::SECONDS; } else if (digits.size() > 6) { point = arr.size() - 6; suffix = "ms"; unit = kj::MILLISECONDS; } else if (digits.size() > 3) { point = arr.size() - 3; suffix = "μs"; unit = kj::MICROSECONDS; } else { point = arr.size(); suffix = "ns"; unit = kj::NANOSECONDS; } CappedArray result; char* begin = result.begin(); char* end; if (negative) { *begin++ = '-'; } if (d % unit == 0 * kj::NANOSECONDS) { end = _::fillLimited(begin, result.end(), arr.slice(0, point), suffix); } else { while (arr.back() == '0') { arr = arr.slice(0, arr.size() - 1); } KJ_DASSERT(arr.size() > point); end = _::fillLimited(begin, result.end(), arr.slice(0, point), "."_kj, arr.slice(point, arr.size()), suffix); } result.setSize(end - result.begin()); return result; } } // namespace kj capnproto-c++-1.1.0/src/kj/async.h0000644000175000017500000017650714712011043017434 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "async-prelude.h" #include #include KJ_BEGIN_HEADER #ifndef KJ_USE_FIBERS #if __BIONIC__ || __FreeBSD__ || __OpenBSD__ || KJ_NO_EXCEPTIONS // These platforms don't support fibers. #define KJ_USE_FIBERS 0 #else #define KJ_USE_FIBERS 1 #endif #else #if KJ_NO_EXCEPTIONS && KJ_USE_FIBERS #error "Fibers cannot be enabled when exceptions are disabled." #endif #endif namespace kj { class EventLoop; class WaitScope; template class Promise; template class ForkedPromise; template class PromiseFulfiller; template struct PromiseFulfillerPair; template class FunctionParam; template using PromiseForResult = _::ReducePromises<_::ReturnType>; // Evaluates to the type of Promise for the result of calling functor type Func with parameter type // T. If T is void, then the promise is for the result of calling Func with no arguments. If // Func itself returns a promise, the promises are joined, so you never get Promise>. // ======================================================================================= class AsyncObject { // You may optionally inherit privately from this to indicate that the type is a KJ async object, // meaning it deals with KJ async I/O making it tied to a specific thread and event loop. This // enables some additional debug checks, but does not otherwise have any effect on behavior as // long as there are no bugs. // // (We prefer inheritance rather than composition here because inheriting an empty type adds zero // size to the derived class.) public: ~AsyncObject(); private: KJ_NORETURN(static void failed() noexcept); }; class DisallowAsyncDestructorsScope { // Create this type on the stack in order to specify that during its scope, no KJ async objects // should be destroyed. If AsyncObject's destructor is called in this scope, the process will // crash with std::terminate(). // // This is useful as a sort of "sanitizer" to catch bugs. When tearing down an object that is // intended to be passed between threads, you can set up one of these scopes to catch whether // the object contains any async objects, which are not legal to pass across threads. public: explicit DisallowAsyncDestructorsScope(kj::StringPtr reason); ~DisallowAsyncDestructorsScope(); KJ_DISALLOW_COPY_AND_MOVE(DisallowAsyncDestructorsScope); private: kj::StringPtr reason; DisallowAsyncDestructorsScope* previousValue; friend class AsyncObject; }; class AllowAsyncDestructorsScope { // Negates the effect of DisallowAsyncDestructorsScope. public: AllowAsyncDestructorsScope(); ~AllowAsyncDestructorsScope(); KJ_DISALLOW_COPY_AND_MOVE(AllowAsyncDestructorsScope); private: DisallowAsyncDestructorsScope* previousValue; }; // ======================================================================================= // Promises template class Promise: protected _::PromiseBase { // The basic primitive of asynchronous computation in KJ. Similar to "futures", but designed // specifically for event loop concurrency. Similar to E promises and JavaScript Promises/A. // // A Promise represents a promise to produce a value of type T some time in the future. Once // that value has been produced, the promise is "fulfilled". Alternatively, a promise can be // "broken", with an Exception describing what went wrong. You may implicitly convert a value of // type T to an already-fulfilled Promise. You may implicitly convert the constant // `kj::READY_NOW` to an already-fulfilled Promise. You may also implicitly convert a // `kj::Exception` to an already-broken promise of any type. // // Promises are linear types -- they are moveable but not copyable. If a Promise is destroyed // or goes out of scope (without being moved elsewhere), any ongoing asynchronous operations // meant to fulfill the promise will be canceled if possible. All methods of `Promise` (unless // otherwise noted) actually consume the promise in the sense of move semantics. (Arguably they // should be rvalue-qualified, but at the time this interface was created compilers didn't widely // support that yet and anyway it would be pretty ugly typing kj::mv(promise).whatever().) If // you want to use one Promise in two different places, you must fork it with `fork()`. // // To use the result of a Promise, you must call `then()` and supply a callback function to // call with the result. `then()` returns another promise, for the result of the callback. // Any time that this would result in Promise>, the promises are collapsed into a // simple Promise that first waits for the outer promise, then the inner. Example: // // // Open a remote file, read the content, and then count the // // number of lines of text. // // Note that none of the calls here block. `file`, `content` // // and `lineCount` are all initialized immediately before any // // asynchronous operations occur. The lambda callbacks are // // called later. // Promise> file = openFtp("ftp://host/foo/bar"); // Promise content = file.then( // [](Own file) -> Promise { // return file.readAll(); // }); // Promise lineCount = content.then( // [](String text) -> int { // uint count = 0; // for (char c: text) count += (c == '\n'); // return count; // }); // // For `then()` to work, the current thread must have an active `EventLoop`. Each callback // is scheduled to execute in that loop. Since `then()` schedules callbacks only on the current // thread's event loop, you do not need to worry about two callbacks running at the same time. // You will need to set up at least one `EventLoop` at the top level of your program before you // can use promises. // // To adapt a non-Promise-based asynchronous API to promises, use `newAdaptedPromise()`. // // Systems using promises should consider supporting the concept of "pipelining". Pipelining // means allowing a caller to start issuing method calls against a promised object before the // promise has actually been fulfilled. This is particularly useful if the promise is for a // remote object living across a network, as this can avoid round trips when chaining a series // of calls. It is suggested that any class T which supports pipelining implement a subclass of // Promise which adds "eventual send" methods -- methods which, when called, say "please // invoke the corresponding method on the promised value once it is available". These methods // should in turn return promises for the eventual results of said invocations. Cap'n Proto, // for example, implements the type `RemotePromise` which supports pipelining RPC requests -- see // `capnp/capability.h`. // // KJ Promises are based on E promises: // http://wiki.erights.org/wiki/Walnut/Distributed_Computing#Promises // // KJ Promises are also inspired in part by the evolving standards for JavaScript/ECMAScript // promises, which are themselves influenced by E promises: // http://promisesaplus.com/ // https://github.com/domenic/promises-unwrapping public: Promise(_::FixVoid value); // Construct an already-fulfilled Promise from a value of type T. For non-void promises, the // parameter type is simply T. So, e.g., in a function that returns `Promise`, you can // say `return 123;` to return a promise that is already fulfilled to 123. // // For void promises, use `kj::READY_NOW` as the value, e.g. `return kj::READY_NOW`. Promise(kj::Exception&& e); // Construct an already-broken Promise. inline Promise(decltype(nullptr)) {} template PromiseForResult then(Func&& func, ErrorFunc&& errorHandler = _::PropagateException(), SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Register a continuation function to be executed when the promise completes. The continuation // (`func`) takes the promised value (an rvalue of type `T`) as its parameter. The continuation // may return a new value; `then()` itself returns a promise for the continuation's eventual // result. If the continuation itself returns a `Promise`, then `then()` shall also return // a `Promise` which first waits for the original promise, then executes the continuation, // then waits for the inner promise (i.e. it automatically "unwraps" the promise). // // In all cases, `then()` returns immediately. The continuation is executed later. The // continuation is always executed on the same EventLoop (and, therefore, the same thread) which // called `then()`, therefore no synchronization is necessary on state shared by the continuation // and the surrounding scope. If no EventLoop is running on the current thread, `then()` throws // an exception. // // You may also specify an error handler continuation as the second parameter. `errorHandler` // must be a functor taking a parameter of type `kj::Exception&&`. It must return the same // type as `func` returns (except when `func` returns `Promise`, in which case `errorHandler` // may return either `Promise` or just `U`). The default error handler simply propagates the // exception to the returned promise. // // Either `func` or `errorHandler` may, of course, throw an exception, in which case the promise // is broken. When compiled with -fno-exceptions, the framework will still detect when a // recoverable exception was thrown inside of a continuation and will consider the promise // broken even though a (presumably garbage) result was returned. // // If the returned promise is destroyed before the callback runs, the callback will be canceled // (it will never run). // // Note that `then()` -- like all other Promise methods -- consumes the promise on which it is // called, in the sense of move semantics. After returning, the original promise is no longer // valid, but `then()` returns a new promise. // // *Advanced implementation tips:* Most users will never need to worry about the below, but // it is good to be aware of. // // As an optimization, if the callback function `func` does _not_ return another promise, then // execution of `func` itself may be delayed until its result is known to be needed. The // expectation here is that `func` is just doing some transformation on the results, not // scheduling any other actions, therefore the system doesn't need to be proactive about // evaluating it. This way, a chain of trivial then() transformations can be executed all at // once without repeatedly re-scheduling through the event loop. Use the `eagerlyEvaluate()` // method to suppress this behavior. // // On the other hand, if `func` _does_ return another promise, then the system evaluates `func` // as soon as possible, because the promise it returns might be for a newly-scheduled // long-running asynchronous task. // // As another optimization, when a callback function registered with `then()` is actually // scheduled, it is scheduled to occur immediately, preempting other work in the event queue. // This allows a long chain of `then`s to execute all at once, improving cache locality by // clustering operations on the same data. However, this implies that starvation can occur // if a chain of `then()`s takes a very long time to execute without ever stopping to wait for // actual I/O. To solve this, use `kj::evalLater()` to yield control; this way, all other events // in the queue will get a chance to run before your callback is executed. Promise ignoreResult() KJ_WARN_UNUSED_RESULT { return then([](T&&) {}); } // Convenience method to convert the promise to a void promise by ignoring the return value. // // You must still wait on the returned promise if you want the task to execute. template Promise catch_(ErrorFunc&& errorHandler, SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Equivalent to `.then(identityFunc, errorHandler)`, where `identifyFunc` is a function that // just returns its input. T wait(WaitScope& waitScope, SourceLocation location = {}); // Run the event loop until the promise is fulfilled, then return its result. If the promise // is rejected, throw an exception. // // wait() is primarily useful at the top level of a program -- typically, within the function // that allocated the EventLoop. For example, a program that performs one or two RPCs and then // exits would likely use wait() in its main() function to wait on each RPC. On the other hand, // server-side code generally cannot use wait(), because it has to be able to accept multiple // requests at once. // // If the promise is rejected, `wait()` throws an exception. If the program was compiled without // exceptions (-fno-exceptions), this will usually abort. In this case you really should first // use `then()` to set an appropriate handler for the exception case, so that the promise you // actually wait on never throws. // // `waitScope` is an object proving that the caller is in a scope where wait() is allowed. By // convention, any function which might call wait(), or which might call another function which // might call wait(), must take `WaitScope&` as one of its parameters. This is needed for two // reasons: // * `wait()` is not allowed during an event callback, because event callbacks are themselves // called during some other `wait()`, and such recursive `wait()`s would only be able to // complete in LIFO order, which might mean that the outer `wait()` ends up waiting longer // than it is supposed to. To prevent this, a `WaitScope` cannot be constructed or used during // an event callback. // * Since `wait()` runs the event loop, unrelated event callbacks may execute before `wait()` // returns. This means that anyone calling `wait()` must be reentrant -- state may change // around them in arbitrary ways. Therefore, callers really need to know if a function they // are calling might wait(), and the `WaitScope&` parameter makes this clear. // // Usually, there is only one `WaitScope` for each `EventLoop`, and it can only be used at the // top level of the thread owning the loop. Calling `wait()` with this `WaitScope` is what // actually causes the event loop to run at all. This top-level `WaitScope` cannot be used // recursively, so cannot be used within an event callback. // // However, it is possible to obtain a `WaitScope` in lower-level code by using fibers. Use // kj::startFiber() to start some code executing on an alternate call stack. That code will get // its own `WaitScope` allowing it to operate in a synchronous style. In this case, `wait()` // switches back to the main stack in order to run the event loop, returning to the fiber's stack // once the awaited promise resolves. bool poll(WaitScope& waitScope, SourceLocation location = {}); // Returns true if a call to wait() would complete without blocking, false if it would block. // // If the promise is not yet resolved, poll() will pump the event loop and poll for I/O in an // attempt to resolve it. Only when there is nothing left to do will it return false. // // Generally, poll() is most useful in tests. Often, you may want to verify that a promise does // not resolve until some specific event occurs. To do so, poll() the promise before the event to // verify it isn't resolved, then trigger the event, then poll() again to verify that it resolves. // The first poll() verifies that the promise doesn't resolve early, which would otherwise be // hard to do deterministically. The second poll() allows you to check that the promise has // resolved and avoid a wait() that might deadlock in the case that it hasn't. // // poll() is not supported in fibers; it will throw an exception. ForkedPromise fork(SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Forks the promise, so that multiple different clients can independently wait on the result. // `T` must be copy-constructable for this to work. Or, in the special case where `T` is // `Own`, `U` must have a method `Own addRef()` which returns a new reference to the same // (or an equivalent) object (probably implemented via reference counting). _::SplitTuplePromise split(SourceLocation location = {}); // Split a promise for a tuple into a tuple of promises. // // E.g. if you have `Promise>`, `split()` returns // `kj::Tuple, Promise>`. Promise exclusiveJoin(Promise&& other, SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Return a new promise that resolves when either the original promise resolves or `other` // resolves (whichever comes first). The promise that didn't resolve first is canceled. // TODO(someday): inclusiveJoin(), or perhaps just join(), which waits for both completions // and produces a tuple? template Promise attach(Attachments&&... attachments) KJ_WARN_UNUSED_RESULT; // "Attaches" one or more movable objects (often, Owns) to the promise, such that they will // be destroyed when the promise resolves. This is useful when a promise's callback contains // pointers into some object and you want to make sure the object still exists when the callback // runs -- after calling then(), use attach() to add necessary objects to the result. template Promise eagerlyEvaluate(ErrorFunc&& errorHandler, SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; Promise eagerlyEvaluate(decltype(nullptr), SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Force eager evaluation of this promise. Use this if you are going to hold on to the promise // for awhile without consuming the result, but you want to make sure that the system actually // processes it. // // `errorHandler` is a function that takes `kj::Exception&&`, like the second parameter to // `then()`, or the parameter to `catch_()`. We make you specify this because otherwise it's // easy to forget to handle errors in a promise that you never use. You may specify nullptr for // the error handler if you are sure that ignoring errors is fine, or if you know that you'll // eventually wait on the promise somewhere. template void detach(ErrorFunc&& errorHandler); // Allows the promise to continue running in the background until it completes or the // `EventLoop` is destroyed. Be careful when using this: since you can no longer cancel this // promise, you need to make sure that the promise owns all the objects it touches or make sure // those objects outlive the EventLoop. // // `errorHandler` is a function that takes `kj::Exception&&`, like the second parameter to // `then()`, except that it must return void. // // This function exists mainly to implement the Cap'n Proto requirement that RPC calls cannot be // canceled unless the callee explicitly permits it. kj::String trace(); // Returns a dump of debug info about this promise. Not for production use. Requires RTTI. // This method does NOT consume the promise as other methods do. private: Promise(bool, _::OwnPromiseNode&& node): PromiseBase(kj::mv(node)) {} // Second parameter prevent ambiguity with immediate-value constructor. friend class _::PromiseNode; }; template class ForkedPromise { // The result of `Promise::fork()` and `EventLoop::fork()`. Allows branches to be created. // Like `Promise`, this is a pass-by-move type. public: inline ForkedPromise(decltype(nullptr)) {} Promise addBranch(); // Add a new branch to the fork. The branch is equivalent to the original promise. bool hasBranches(); // Returns true if there are any branches that haven't been canceled. private: Own<_::ForkHub<_::FixVoid>> hub; inline ForkedPromise(bool, Own<_::ForkHub<_::FixVoid>>&& hub): hub(kj::mv(hub)) {} friend class Promise; friend class EventLoop; }; constexpr _::ReadyNow READY_NOW = _::ReadyNow(); // Use this when you need a Promise that is already fulfilled -- this value can be implicitly // cast to `Promise`. constexpr _::NeverDone NEVER_DONE = _::NeverDone(); // The opposite of `READY_NOW`, return this when the promise should never resolve. This can be // implicitly converted to any promise type. You may also call `NEVER_DONE.wait()` to wait // forever (useful for servers). template Promise constPromise(); // Construct a Promise which resolves to the given constant value. This function is equivalent to // `Promise(value)` except that it avoids an allocation. template PromiseForResult evalLater(Func&& func) KJ_WARN_UNUSED_RESULT; // Schedule for the given zero-parameter function to be executed in the event loop at some // point in the near future. Returns a Promise for its result -- or, if `func()` itself returns // a promise, `evalLater()` returns a Promise for the result of resolving that promise. // // Example usage: // Promise x = evalLater([]() { return 123; }); // // The above is exactly equivalent to: // Promise x = Promise(READY_NOW).then([]() { return 123; }); // // If the returned promise is destroyed before the callback runs, the callback will be canceled // (never called). // // If you schedule several evaluations with `evalLater` during the same callback, they are // guaranteed to be executed in order. template PromiseForResult evalNow(Func&& func) KJ_WARN_UNUSED_RESULT; // Run `func()` and return a promise for its result. `func()` executes before `evalNow()` returns. // If `func()` throws an exception, the exception is caught and wrapped in a promise -- this is the // main reason why `evalNow()` is useful. template PromiseForResult evalLast(Func&& func) KJ_WARN_UNUSED_RESULT; // Like `evalLater()`, except that the function doesn't run until the event queue is otherwise // completely empty and the thread is about to suspend waiting for I/O. // // This is useful when you need to perform some disruptive action and you want to make sure that // you don't interrupt some other task between two .then() continuations. For example, say you want // to cancel a read() operation on a socket and know for sure that if any bytes were read, you saw // them. It could be that a read() has completed and bytes have been transferred to the target // buffer, but the .then() callback that handles the read result hasn't executed yet. If you // cancel the promise at this inopportune moment, the bytes in the buffer are lost. If you do // evalLast(), then you can be sure that any pending .then() callbacks had a chance to finish out // and if you didn't receive the read result yet, then you know nothing has been read, and you can // simply drop the promise. // // If evalLast() is called multiple times, functions are executed in LIFO order. If the first // callback enqueues new events, then latter callbacks will not execute until those events are // drained. ArrayPtr getAsyncTrace(ArrayPtr space); kj::String getAsyncTrace(); // If the event loop is currently running in this thread, get a trace back through the promise // chain leading to the currently-executing event. The format is the same as kj::getStackTrace() // from exception.c++. template PromiseForResult retryOnDisconnect(Func&& func) KJ_WARN_UNUSED_RESULT; // Promises to run `func()` asynchronously, retrying once if it fails with a DISCONNECTED exception. // If the retry also fails, the exception is passed through. // // `func()` should return a `Promise`. `retryOnDisconnect(func)` returns the same promise, except // with the retry logic added. template PromiseForResult startFiber( size_t stackSize, Func&& func, SourceLocation location = {}) KJ_WARN_UNUSED_RESULT; // Executes `func()` in a fiber, returning a promise for the eventual reseult. `func()` will be // passed a `WaitScope&` as its parameter, allowing it to call `.wait()` on promises. Thus, `func()` // can be written in a synchronous, blocking style, instead of using `.then()`. This is often much // easier to write and read, and may even be significantly faster if it allows the use of stack // allocation rather than heap allocation. // // However, fibers have a major disadvantage: memory must be allocated for the fiber's call stack. // The entire stack must be allocated at once, making it necessary to choose a stack size upfront // that is big enough for whatever the fiber needs to do. Estimating this is often difficult. That // said, over-estimating is not too terrible since pages of the stack will actually be allocated // lazily when first accessed; actual memory usage will correspond to the "high watermark" of the // actual stack usage. That said, this lazy allocation forces page faults, which can be quite slow. // Worse, freeing a stack forces a TLB flush and shootdown -- all currently-executing threads will // have to be interrupted to flush their CPU cores' TLB caches. // // In short, when performance matters, you should try to avoid creating fibers very frequently. class FiberPool final { // A freelist pool of fibers with a set stack size. This improves CPU usage with fibers at // the expense of memory usage. Fibers in this pool will always use the max amount of memory // used until the pool is destroyed. public: explicit FiberPool(size_t stackSize); ~FiberPool() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(FiberPool); void setMaxFreelist(size_t count); // Set the maximum number of stacks to add to the freelist. If the freelist is full, stacks will // be deleted rather than returned to the freelist. void useCoreLocalFreelists(); // EXPERIMENTAL: Call to tell FiberPool to try to use core-local stack freelists, which // in theory should increase L1/L2 cache efficacy for freelisted stacks. In practice, as of // this writing, no performance advantage has yet been demonstrated. Note that currently this // feature is only supported on Linux (the flag has no effect on other operating systems). template PromiseForResult startFiber( Func&& func, SourceLocation location = {}) const KJ_WARN_UNUSED_RESULT; // Executes `func()` in a fiber from this pool, returning a promise for the eventual result. // `func()` will be passed a `WaitScope&` as its parameter, allowing it to call `.wait()` on // promises. Thus, `func()` can be written in a synchronous, blocking style, instead of // using `.then()`. This is often much easier to write and read, and may even be significantly // faster if it allows the use of stack allocation rather than heap allocation. void runSynchronously(kj::FunctionParam func) const; // Use one of the stacks in the pool to synchronously execute func(), returning the result that // func() returns. This is not the usual use case for fibers, but can be a nice optimization // in programs that have many threads that mostly only need small stacks, but occasionally need // a much bigger stack to run some deeply recursive algorithm. If the algorithm is run on each // thread's normal call stack, then every thread's stack will tend to grow to be very big // (usually, stacks automatically grow as needed, but do not shrink until the thread exits // completely). If the thread can share a small set of big stacks that they use only when calling // the deeply recursive algorithm, and use small stacks for everything else, overall memory usage // is reduced. // // TODO(someday): If func() returns a value, return it from runSynchronously? Current use case // doesn't need it. size_t getFreelistSize() const; // Get the number of stacks currently in the freelist. Does not count stacks that are active. private: class Impl; Own impl; friend class _::FiberStack; friend class _::FiberBase; }; template Promise> joinPromises(Array>&& promises, SourceLocation location = {}); // Join an array of promises into a promise for an array. Trailing continuations on promises are not // evaluated until all promises have settled. Exceptions are propagated only after the last promise // has settled. // // TODO(cleanup): It is likely that `joinPromisesFailFast()` is what everyone should be using. // Deprecate this function. template Promise> joinPromisesFailFast(Array>&& promises, SourceLocation location = {}); // Join an array of promises into a promise for an array. Trailing continuations on promises are // evaluated eagerly. If any promise results in an exception, the exception is immediately // propagated to the returned join promise. // ======================================================================================= // Hack for creating a lambda that holds an owned pointer. template class CaptureByMove { public: inline CaptureByMove(Func&& func, MovedParam&& param) : func(kj::mv(func)), param(kj::mv(param)) {} template inline auto operator()(Params&&... params) -> decltype(kj::instance()(kj::instance(), kj::fwd(params)...)) { return func(kj::mv(param), kj::fwd(params)...); } private: Func func; MovedParam param; }; template inline CaptureByMove> mvCapture(MovedParam&& param, Func&& func) KJ_DEPRECATED("Use C++14 generalized captures instead."); template inline CaptureByMove> mvCapture(MovedParam&& param, Func&& func) { // Hack to create a "lambda" which captures a variable by moving it rather than copying or // referencing. C++14 generalized captures should make this obsolete, but for now in C++11 this // is commonly needed for Promise continuations that own their state. Example usage: // // Own ptr = makeFoo(); // Promise promise = callRpc(); // promise.then(mvCapture(ptr, [](Own&& ptr, int result) { // return ptr->finish(result); // })); return CaptureByMove>(kj::fwd(func), kj::mv(param)); } // ======================================================================================= // Hack for safely using a lambda as a coroutine. #if KJ_HAS_COROUTINE namespace _ { void throwMultipleCoCaptureInvocations(); template struct CaptureForCoroutine { kj::Maybe maybeFunctor; explicit CaptureForCoroutine(Functor&& f) : maybeFunctor(kj::mv(f)) {} template static auto coInvoke(Functor functor, Args&&... args) -> decltype(functor(kj::fwd(args)...)) { // Since the functor is now in the local scope and no longer a member variable, it will be // persisted in the coroutine state. // Note that `co_await functor(...)` can still return `void`. It just happens that // `co_return voidReturn();` is explicitly allowed. co_return co_await functor(kj::fwd(args)...); } template auto operator()(Args&&... args) { if (maybeFunctor == nullptr) { throwMultipleCoCaptureInvocations(); } auto localFunctor = kj::mv(*kj::_::readMaybe(maybeFunctor)); maybeFunctor = nullptr; return coInvoke(kj::mv(localFunctor), kj::fwd(args)...); } }; } // namespace _ template auto coCapture(Functor&& f) { // Assuming `f()` returns a Promise `p`, wrap `f` in such a way that it will outlive its // returned Promise. Note that the returned object may only be invoked once. // // This function is meant to help address this pain point with functors that return a coroutine: // https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rcoro-capture // // The two most common patterns where this may be useful look like so: // ``` // void addTask(Value myValue) { // auto myFun = [myValue]() -> kj::Promise { // ... // co_return; // }; // tasks.add(myFun()); // } // ``` // and // ``` // kj::Promise afterPromise(kj::Promise promise, Value myValue) { // auto myFun = [myValue]() -> kj::Promise { // ... // co_return; // }; // return promise.then(kj::mv(myFun)); // } // ``` // // Note that there are potentially more optimal alternatives to both of these patterns: // ``` // void addTask(Value myValue) { // auto myFun = [](auto myValue) -> kj::Promise { // ... // co_return; // }; // tasks.add(myFun(myValue)); // } // ``` // and // ``` // kj::Promise afterPromise(kj::Promise promise, Value myValue) { // auto myFun = [&]() -> kj::Promise { // ... // co_return; // }; // co_await promise; // co_await myFun(); // co_return; // } // ``` // // For situations where you are trying to capture a specific local variable, kj::mvCapture() can // also be useful: // ``` // kj::Promise reactToPromise(kj::Promise promise) { // BigA a; // TinyB b; // // doSomething(a, b); // return promise.then(kj::mvCapture(b, [](TinyB b, MyType type) -> kj::Promise { // ... // co_return; // }); // } // ``` return _::CaptureForCoroutine(kj::mv(f)); } #endif // KJ_HAS_COROUTINE // ======================================================================================= // Advanced promise construction class PromiseRejector: private AsyncObject { // Superclass of PromiseFulfiller containing the non-typed methods. Useful when you only really // need to be able to reject a promise, and you need to operate on fulfillers of different types. public: virtual void reject(Exception&& exception) = 0; virtual bool isWaiting() = 0; }; template class PromiseFulfiller: public PromiseRejector { // A callback which can be used to fulfill a promise. Only the first call to fulfill() or // reject() matters; subsequent calls are ignored. public: virtual void fulfill(T&& value) = 0; // Fulfill the promise with the given value. virtual void reject(Exception&& exception) = 0; // Reject the promise with an error. virtual bool isWaiting() = 0; // Returns true if the promise is still unfulfilled and someone is potentially waiting for it. // Returns false if fulfill()/reject() has already been called *or* if the promise to be // fulfilled has been discarded and therefore the result will never be used anyway. template bool rejectIfThrows(Func&& func); // Call the function (with no arguments) and return true. If an exception is thrown, call // `fulfiller.reject()` and then return false. When compiled with exceptions disabled, // non-fatal exceptions are still detected and handled correctly. }; template <> class PromiseFulfiller: public PromiseRejector { // Specialization of PromiseFulfiller for void promises. See PromiseFulfiller. public: virtual void fulfill(_::Void&& value = _::Void()) = 0; // Call with zero parameters. The parameter is a dummy that only exists so that subclasses don't // have to specialize for . virtual void reject(Exception&& exception) = 0; virtual bool isWaiting() = 0; template bool rejectIfThrows(Func&& func); }; template _::ReducePromises newAdaptedPromise(Params&&... adapterConstructorParams); // Creates a new promise which owns an instance of `Adapter` which encapsulates the operation // that will eventually fulfill the promise. This is primarily useful for adapting non-KJ // asynchronous APIs to use promises. // // An instance of `Adapter` will be allocated and owned by the returned `Promise`. A // `PromiseFulfiller&` will be passed as the first parameter to the adapter's constructor, // and `adapterConstructorParams` will be forwarded as the subsequent parameters. The adapter // is expected to perform some asynchronous operation and call the `PromiseFulfiller` once // it is finished. // // The adapter is destroyed when its owning Promise is destroyed. This may occur before the // Promise has been fulfilled. In this case, the adapter's destructor should cancel the // asynchronous operation. Once the adapter is destroyed, the fulfillment callback cannot be // called. // // An adapter implementation should be carefully written to ensure that it cannot accidentally // be left unfulfilled permanently because of an exception. Consider making liberal use of // `PromiseFulfiller::rejectIfThrows()`. template struct PromiseFulfillerPair { _::ReducePromises promise; Own> fulfiller; }; template PromiseFulfillerPair newPromiseAndFulfiller(SourceLocation location = {}); // Construct a Promise and a separate PromiseFulfiller which can be used to fulfill the promise. // If the PromiseFulfiller is destroyed before either of its methods are called, the Promise is // implicitly rejected. // // Although this function is easier to use than `newAdaptedPromise()`, it has the serious drawback // that there is no way to handle cancellation (i.e. detect when the Promise is discarded). // // You can arrange to fulfill a promise with another promise by using a promise type for T. E.g. // `newPromiseAndFulfiller>()` will produce a promise of type `Promise` but the // fulfiller will be of type `PromiseFulfiller>`. Thus you pass a `Promise` to the // `fulfill()` callback, and the promises are chained. template class CrossThreadPromiseFulfiller: public kj::PromiseFulfiller { // Like PromiseFulfiller but the methods are `const`, indicating they can safely be called // from another thread. public: virtual void fulfill(T&& value) const = 0; virtual void reject(Exception&& exception) const = 0; virtual bool isWaiting() const = 0; void fulfill(T&& value) override { return constThis()->fulfill(kj::fwd(value)); } void reject(Exception&& exception) override { return constThis()->reject(kj::mv(exception)); } bool isWaiting() override { return constThis()->isWaiting(); } private: const CrossThreadPromiseFulfiller* constThis() { return this; } }; template <> class CrossThreadPromiseFulfiller: public kj::PromiseFulfiller { // Specialization of CrossThreadPromiseFulfiller for void promises. See // CrossThreadPromiseFulfiller. public: virtual void fulfill(_::Void&& value = _::Void()) const = 0; virtual void reject(Exception&& exception) const = 0; virtual bool isWaiting() const = 0; void fulfill(_::Void&& value) override { return constThis()->fulfill(kj::mv(value)); } void reject(Exception&& exception) override { return constThis()->reject(kj::mv(exception)); } bool isWaiting() override { return constThis()->isWaiting(); } private: const CrossThreadPromiseFulfiller* constThis() { return this; } }; template struct PromiseCrossThreadFulfillerPair { _::ReducePromises promise; Own> fulfiller; }; template PromiseCrossThreadFulfillerPair newPromiseAndCrossThreadFulfiller(); // Like `newPromiseAndFulfiller()`, but the fulfiller is allowed to be invoked from any thread, // not just the one that called this method. Note that the Promise is still tied to the calling // thread's event loop and *cannot* be used from another thread -- only the PromiseFulfiller is // cross-thread. // ======================================================================================= // Canceler class Canceler: private AsyncObject { // A Canceler can wrap some set of Promises and then forcefully cancel them on-demand, or // implicitly when the Canceler is destroyed. // // The cancellation is done in such a way that once cancel() (or the Canceler's destructor) // returns, it's guaranteed that the promise has already been canceled and destroyed. This // guarantee is important for enforcing ownership constraints. For example, imagine that Alice // calls a method on Bob that returns a Promise. That Promise encapsulates a task that uses Bob's // internal state. But, imagine that Alice does not own Bob, and indeed Bob might be destroyed // at random without Alice having canceled the promise. In this case, it is necessary for Bob to // ensure that the promise will be forcefully canceled. Bob can do this by constructing a // Canceler and using it to wrap promises before returning them to callers. When Bob is // destroyed, the Canceler is destroyed too, and all promises Bob wrapped with it throw errors. // // Note that another common strategy for cancellation is to use exclusiveJoin() to join a promise // with some "cancellation promise" which only resolves if the operation should be canceled. The // cancellation promise could itself be created by newPromiseAndFulfiller(), and thus // calling the PromiseFulfiller cancels the operation. There is a major problem with this // approach: upon invoking the fulfiller, an arbitrary amount of time may pass before the // exclusive-joined promise actually resolves and cancels its other fork. During that time, the // task might continue to execute. If it holds pointers to objects that have been destroyed, this // might cause segfaults. Thus, it is safer to use a Canceler. public: inline Canceler() {} ~Canceler() noexcept(false); KJ_DISALLOW_COPY_AND_MOVE(Canceler); template Promise wrap(Promise promise) { return newAdaptedPromise>(*this, kj::mv(promise)); } void cancel(StringPtr cancelReason); void cancel(const Exception& exception); // Cancel all previously-wrapped promises that have not already completed, causing them to throw // the given exception. If you provide just a description message instead of an exception, then // an exception object will be constructed from it -- but only if there are requests to cancel. void release(); // Releases previously-wrapped promises, so that they will not be canceled regardless of what // happens to this Canceler. bool isEmpty() const { return list == nullptr; } // Indicates if any previously-wrapped promises are still executing. (If this returns true, then // cancel() would be a no-op.) private: class AdapterBase { public: AdapterBase(Canceler& canceler); ~AdapterBase() noexcept(false); virtual void cancel(Exception&& e) = 0; void unlink(); private: Maybe&> prev; Maybe next; friend class Canceler; }; template class AdapterImpl: public AdapterBase { public: AdapterImpl(PromiseFulfiller& fulfiller, Canceler& canceler, Promise inner) : AdapterBase(canceler), fulfiller(fulfiller), inner(inner.then( [&fulfiller](T&& value) { fulfiller.fulfill(kj::mv(value)); }, [&fulfiller](Exception&& e) { fulfiller.reject(kj::mv(e)); }) .eagerlyEvaluate(nullptr)) {} void cancel(Exception&& e) override { fulfiller.reject(kj::mv(e)); inner = nullptr; } private: PromiseFulfiller& fulfiller; Promise inner; }; Maybe list; }; template <> class Canceler::AdapterImpl: public AdapterBase { public: AdapterImpl(kj::PromiseFulfiller& fulfiller, Canceler& canceler, kj::Promise inner); void cancel(kj::Exception&& e) override; // These must be defined in async.c++ to prevent translation units compiled by MSVC from trying to // link with symbols defined in async.c++ merely because they included async.h. private: kj::PromiseFulfiller& fulfiller; kj::Promise inner; }; // ======================================================================================= // TaskSet class TaskSet: private AsyncObject { // Holds a collection of Promises and ensures that each executes to completion. Memory // associated with each promise is automatically freed when the promise completes. Destroying // the TaskSet itself automatically cancels all unfinished promises. // // This is useful for "daemon" objects that perform background tasks which aren't intended to // fulfill any particular external promise, but which may need to be canceled (and thus can't // use `Promise::detach()`). The daemon object holds a TaskSet to collect these tasks it is // working on. This way, if the daemon itself is destroyed, the TaskSet is destroyed as well, // and everything the daemon is doing is canceled. public: class ErrorHandler { public: virtual void taskFailed(kj::Exception&& exception) = 0; }; TaskSet(ErrorHandler& errorHandler, SourceLocation location = {}); // `errorHandler` will be executed any time a task throws an exception, and will execute within // the given EventLoop. ~TaskSet() noexcept(false); void add(Promise&& promise); kj::String trace(); // Return debug info about all promises currently in the TaskSet. bool isEmpty() { return tasks == nullptr; } // Check if any tasks are running. Promise onEmpty(); // Returns a promise that fulfills the next time the TaskSet is empty. Only one such promise can // exist at a time. void clear(); // Cancel all tasks. // // As always, it is not safe to cancel the task that is currently running, so you could not call // this from inside a task in the TaskSet. However, it IS safe to call this from the // `taskFailed()` callback. // // Calling this will always trigger onEmpty(), if anyone is listening. private: class Task; using OwnTask = Own; TaskSet::ErrorHandler& errorHandler; Maybe tasks; Maybe>> emptyFulfiller; SourceLocation location; }; // ======================================================================================= // Cross-thread execution. class Executor { // Executes code on another thread's event loop. // // Use `kj::getCurrentThreadExecutor()` to get an executor that schedules calls on the current // thread's event loop. You may then pass the reference to other threads to enable them to call // back to this one. public: Executor(EventLoop& loop, Badge); ~Executor() noexcept(false); virtual kj::Own addRef() const = 0; // Add a reference to this Executor. The Executor will not be destroyed until all references are // dropped. This uses atomic refcounting for thread-safety. // // Use this when you can't guarantee that the target thread's event loop won't concurrently exit // (including due to an uncaught exception!) while another thread is still using the Executor. // Otherwise, the Executor object is destroyed when the owning event loop exits. // // If the target event loop has exited, then `execute{Async,Sync}` will throw DISCONNECTED // exceptions. bool isLive() const; // Returns true if the remote event loop still exists, false if it has been destroyed. In the // latter case, `execute{Async,Sync}()` will definitely throw. Of course, if this returns true, // it could still change to false at any moment, and `execute{Async,Sync}()` could still throw as // a result. // // TODO(cleanup): Should we have tryExecute{Async,Sync}() that return Maybes that are null if // the remote event loop exited? Currently there are multiple known use cases that check // isLive() after catching a DISCONNECTED exception to decide whether it is due to the executor // exiting, and then handling that case. This is borderline in violation of KJ exception // philosophy, but right now I'm not excited about the extra template metaprogramming needed // for "try" versions... template PromiseForResult executeAsync(Func&& func, SourceLocation location = {}) const; // Call from any thread to request that the given function be executed on the executor's thread, // returning a promise for the result. // // The Promise returned by executeAsync() belongs to the requesting thread, not the executor // thread. Hence, for example, continuations added to this promise with .then() will execute in // the requesting thread. // // If func() itself returns a Promise, that Promise is *not* returned verbatim to the requesting // thread -- after all, Promise objects cannot be used cross-thread. Instead, the executor thread // awaits the promise. Once it resolves to a final result, that result is transferred to the // requesting thread, resolving the promise that executeAsync() returned earlier. // // `func` will be destroyed in the requesting thread, after the final result has been returned // from the executor thread. This means that it is safe for `func` to capture objects that cannot // safely be destroyed from another thread. It is also safe for `func` to be an lvalue reference, // so long as the functor remains live until the promise completes or is canceled, and the // function is thread-safe. // // Of course, the body of `func` must be careful that any access it makes on these objects is // safe cross-thread. For example, it must not attempt to access Promise-related objects // cross-thread; you cannot create a `PromiseFulfiller` in one thread and then `fulfill()` it // from another. Unfortunately, the usual convention of using const-correctness to enforce // thread-safety does not work here, because applications can often ensure that `func` has // exclusive access to captured objects, and thus can safely mutate them even in non-thread-safe // ways; the const qualifier is not sufficient to express this. // // The final return value of `func` is transferred between threads, and hence is constructed and // destroyed in separate threads. It is the app's responsibility to make sure this is OK. // Alternatively, the app can perhaps arrange to send the return value back to the original // thread for destruction, if needed. // // If the requesting thread destroys the returned Promise, the destructor will block waiting for // the executor thread to acknowledge cancellation. This ensures that `func` can be destroyed // before the Promise's destructor returns. // // Multiple calls to executeAsync() from the same requesting thread to the same target thread // will be delivered in the same order in which they were requested. (However, if func() returns // a promise, delivery of subsequent calls is not blocked on that promise. In other words, this // call provides E-Order in the same way as Cap'n Proto.) template _::UnwrapPromise> executeSync( Func&& func, SourceLocation location = {}) const; // Schedules `func()` to execute on the executor thread, and then blocks the requesting thread // until `func()` completes. If `func()` returns a Promise, then the wait will continue until // that promise resolves, and the final result will be returned to the requesting thread. // // The requesting thread does not need to have an EventLoop. If it does have an EventLoop, that // loop will *not* execute while the thread is blocked. This method is particularly useful to // allow non-event-loop threads to perform I/O via a separate event-loop thread. // // As with `executeAsync()`, `func` is always destroyed on the requesting thread, after the // executor thread has signaled completion. The return value is transferred between threads. private: struct Impl; Own impl; // To avoid including mutex.h... friend class EventLoop; friend class _::XThreadEvent; friend class _::XThreadPaf; void send(_::XThreadEvent& event, bool sync) const; void wait(); bool poll(); EventLoop& getLoop() const; }; const Executor& getCurrentThreadExecutor(); // Get the executor for the current thread's event loop. This reference can then be passed to other // threads. // ======================================================================================= // The EventLoop class class EventPort { // Interfaces between an `EventLoop` and events originating from outside of the loop's thread. // All such events come in through the `EventPort` implementation. // // An `EventPort` implementation may interface with low-level operating system APIs and/or other // threads. You can also write an `EventPort` which wraps some other (non-KJ) event loop // framework, allowing the two to coexist in a single thread. public: virtual bool wait() = 0; // Wait for an external event to arrive, sleeping if necessary. Once at least one event has // arrived, queue it to the event loop (e.g. by fulfilling a promise) and return. // // This is called during `Promise::wait()` whenever the event queue becomes empty, in order to // wait for new events to populate the queue. // // It is safe to return even if nothing has actually been queued, so long as calling `wait()` in // a loop will eventually sleep. (That is to say, false positives are fine.) // // Returns true if wake() has been called from another thread. (Precisely, returns true if // no previous call to wait `wait()` nor `poll()` has returned true since `wake()` was last // called.) virtual bool poll() = 0; // Check if any external events have arrived, but do not sleep. If any events have arrived, // add them to the event queue (e.g. by fulfilling promises) before returning. // // This may be called during `Promise::wait()` when the EventLoop has been executing for a while // without a break but is still non-empty. // // Returns true if wake() has been called from another thread. (Precisely, returns true if // no previous call to wait `wait()` nor `poll()` has returned true since `wake()` was last // called.) virtual void setRunnable(bool runnable); // Called to notify the `EventPort` when the `EventLoop` has work to do; specifically when it // transitions from empty -> runnable or runnable -> empty. This is typically useful when // integrating with an external event loop; if the loop is currently runnable then you should // arrange to call run() on it soon. The default implementation does nothing. virtual void wake() const; // Wake up the EventPort's thread from another thread. // // Unlike all other methods on this interface, `wake()` may be called from another thread, hence // it is `const`. // // Technically speaking, `wake()` causes the target thread to cease sleeping and not to sleep // again until `wait()` or `poll()` has returned true at least once. // // The default implementation throws an UNIMPLEMENTED exception. }; class EventLoop { // Represents a queue of events being executed in a loop. Most code won't interact with // EventLoop directly, but instead use `Promise`s to interact with it indirectly. See the // documentation for `Promise`. // // Each thread can have at most one current EventLoop. To make an `EventLoop` current for // the thread, create a `WaitScope`. Async APIs require that the thread has a current EventLoop, // or they will throw exceptions. APIs that use `Promise::wait()` additionally must explicitly // be passed a reference to the `WaitScope` to make the caller aware that they might block. // // Generally, you will want to construct an `EventLoop` at the top level of your program, e.g. // in the main() function, or in the start function of a thread. You can then use it to // construct some promises and wait on the result. Example: // // int main() { // // `loop` becomes the official EventLoop for the thread. // MyEventPort eventPort; // EventLoop loop(eventPort); // // // Now we can call an async function. // Promise textPromise = getHttp("http://example.com"); // // // And we can wait for the promise to complete. Note that you can only use `wait()` // // from the top level, not from inside a promise callback. // String text = textPromise.wait(); // print(text); // return 0; // } // // Most applications that do I/O will prefer to use `setupAsyncIo()` from `async-io.h` rather // than allocate an `EventLoop` directly. public: EventLoop(); // Construct an `EventLoop` which does not receive external events at all. explicit EventLoop(EventPort& port); // Construct an `EventLoop` which receives external events through the given `EventPort`. ~EventLoop() noexcept(false); void run(uint maxTurnCount = maxValue); // Run the event loop for `maxTurnCount` turns or until there is nothing left to be done, // whichever comes first. This never calls the `EventPort`'s `sleep()` or `poll()`. It will // call the `EventPort`'s `setRunnable(false)` if the queue becomes empty. bool isRunnable(); // Returns true if run() would currently do anything, or false if the queue is empty. const Executor& getExecutor(); // Returns an Executor that can be used to schedule events on this EventLoop from another thread. // // Use the global function kj::getCurrentThreadExecutor() to get the current thread's EventLoop's // Executor. // // Note that this is only needed for cross-thread scheduling. To schedule code to run later in // the current thread, use `kj::evalLater()`, which will be more efficient. private: kj::Maybe port; // If null, this thread doesn't receive I/O events from the OS. It can potentially receive // events from other threads via the Executor. bool running = false; // True while looping -- wait() is then not allowed. bool lastRunnableState = false; // What did we last pass to port.setRunnable()? _::Event* head = nullptr; _::Event** tail = &head; _::Event** depthFirstInsertPoint = &head; _::Event** breadthFirstInsertPoint = &head; kj::Maybe> executor; // Allocated the first time getExecutor() is requested, making cross-thread request possible. Own daemons; _::Event* currentlyFiring = nullptr; bool turn(); void setRunnable(bool runnable); void enterScope(); void leaveScope(); void wait(); void poll(); friend void _::detach(kj::Promise&& promise); friend void _::waitImpl(_::OwnPromiseNode&& node, _::ExceptionOrValue& result, WaitScope& waitScope, SourceLocation location); friend bool _::pollImpl(_::PromiseNode& node, WaitScope& waitScope, SourceLocation location); friend class _::Event; friend class WaitScope; friend class Executor; friend class _::XThreadEvent; friend class _::XThreadPaf; friend class _::FiberBase; friend class _::FiberStack; friend ArrayPtr getAsyncTrace(ArrayPtr space); }; class WaitScope { // Represents a scope in which asynchronous programming can occur. A `WaitScope` should usually // be allocated on the stack and serves two purposes: // * While the `WaitScope` exists, its `EventLoop` is registered as the current loop for the // thread. Most operations dealing with `Promise` (including all of its methods) do not work // unless the thread has a current `EventLoop`. // * `WaitScope` may be passed to `Promise::wait()` to synchronously wait for a particular // promise to complete. See `Promise::wait()` for an extended discussion. public: inline explicit WaitScope(EventLoop& loop): loop(loop) { loop.enterScope(); } inline ~WaitScope() { if (fiber == nullptr) loop.leaveScope(); } KJ_DISALLOW_COPY_AND_MOVE(WaitScope); uint poll(uint maxTurnCount = maxValue); // Pumps the event queue and polls for I/O until there's nothing left to do (without blocking) or // the maximum turn count has been reached. Returns the number of events popped off the event // queue. // // Not supported in fibers. void setBusyPollInterval(uint count) { busyPollInterval = count; } // Set the maximum number of events to run in a row before calling poll() on the EventPort to // check for new I/O. // // This has no effect when used in a fiber. void runEventCallbacksOnStackPool(kj::Maybe pool) { runningStacksPool = pool; } // Arranges to switch stacks while event callbacks are executing. This is an optimization that // is useful for programs that use extremely high thread counts, where each thread has its own // event loop, but each thread has relatively low event throughput, i.e. each thread spends // most of its time waiting for I/O. Normally, the biggest problem with having lots of threads // is that each thread must allocate a stack, and stacks can take a lot of memory if the // application commonly makes deep calls. But, most of that stack space is only needed while // the thread is executing, not while it's sleeping. So, if threads only switch to a big stack // during execution, switching back when it's time to sleep, and if those stacks are freelisted // so that they can be shared among threads, then a lot of memory is saved. // // We use the `FiberPool` type here because it implements a freelist of stacks, which is exactly // what we happen to want! In our case, though, we don't use those stacks to implement fibers; // we use them as the main thread stack. // // This has no effect if this WaitScope itself is for a fiber. // // Pass `nullptr` as the parameter to go back to running events on the main stack. void cancelAllDetached(); // HACK: Immediately cancel all detached promises. // // New code should not use detached promises, and therefore should not need this. // // This method exists to help existing code deal with the problems of detached promises, // especially at teardown time. // // This method may be removed in the future. private: EventLoop& loop; uint busyPollInterval = kj::maxValue; kj::Maybe<_::FiberBase&> fiber; kj::Maybe runningStacksPool; explicit WaitScope(EventLoop& loop, _::FiberBase& fiber) : loop(loop), fiber(fiber) {} template inline void runOnStackPool(Func&& func) { KJ_IF_MAYBE(pool, runningStacksPool) { pool->runSynchronously(kj::fwd(func)); } else { func(); } } friend class EventLoop; friend class _::FiberBase; friend void _::waitImpl(_::OwnPromiseNode&& node, _::ExceptionOrValue& result, WaitScope& waitScope, SourceLocation location); friend bool _::pollImpl(_::PromiseNode& node, WaitScope& waitScope, SourceLocation location); }; } // namespace kj #define KJ_ASYNC_H_INCLUDED #include "async-inl.h" KJ_END_HEADER capnproto-c++-1.1.0/src/kj/array-test.c++0000644000175000017500000003404614712011043020522 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "array.h" #include "debug.h" #include #include #include namespace kj { namespace { struct TestObject { TestObject() { index = count; KJ_ASSERT(index != throwAt); ++count; } TestObject(const TestObject& other) { KJ_ASSERT(other.index != throwAt); index = -1; copiedCount++; } ~TestObject() noexcept(false) { if (index == -1) { --copiedCount; } else { --count; EXPECT_EQ(index, count); KJ_ASSERT(count != throwAt); } } int index; static int count; static int copiedCount; static int throwAt; }; int TestObject::count = 0; int TestObject::copiedCount = 0; int TestObject::throwAt = -1; struct TestNoexceptObject { TestNoexceptObject() noexcept { index = count; ++count; } TestNoexceptObject(const TestNoexceptObject& other) noexcept { index = -1; copiedCount++; } ~TestNoexceptObject() noexcept { if (index == -1) { --copiedCount; } else { --count; EXPECT_EQ(index, count); } } int index; static int count; static int copiedCount; }; int TestNoexceptObject::count = 0; int TestNoexceptObject::copiedCount = 0; TEST(Array, TrivialConstructor) { // char* ptr; { Array chars = heapArray(32); // ptr = chars.begin(); chars[0] = 12; chars[1] = 34; } { Array chars = heapArray(32); // TODO(test): The following doesn't work in opt mode -- I guess some allocators zero the // memory? Is there some other way we can test this? Maybe override malloc()? // // Somewhat hacky: We can't guarantee that the new array is allocated in the same place, but // // any reasonable allocator is highly likely to do so. If it does, then we expect that the // // memory has not been initialized. // if (chars.begin() == ptr) { // EXPECT_NE(chars[0], 0); // EXPECT_NE(chars[1], 0); // } } } TEST(Array, ComplexConstructor) { TestObject::count = 0; TestObject::throwAt = -1; { Array array = heapArray(32); EXPECT_EQ(32, TestObject::count); } EXPECT_EQ(0, TestObject::count); } #if !KJ_NO_EXCEPTIONS TEST(Array, ThrowingConstructor) { TestObject::count = 0; TestObject::throwAt = 16; // If a constructor throws, the previous elements should still be destroyed. EXPECT_ANY_THROW(heapArray(32)); EXPECT_EQ(0, TestObject::count); } TEST(Array, ThrowingDestructor) { TestObject::count = 0; TestObject::throwAt = -1; Array array = heapArray(32); EXPECT_EQ(32, TestObject::count); // If a destructor throws, all elements should still be destroyed. TestObject::throwAt = 16; EXPECT_ANY_THROW(array = nullptr); EXPECT_EQ(0, TestObject::count); } #endif // !KJ_NO_EXCEPTIONS TEST(Array, AraryBuilder) { TestObject::count = 0; TestObject::throwAt = -1; Array array; { ArrayBuilder builder = heapArrayBuilder(32); for (int i = 0; i < 32; i++) { EXPECT_EQ(i, TestObject::count); builder.add(); } EXPECT_EQ(32, TestObject::count); array = builder.finish(); EXPECT_EQ(32, TestObject::count); } EXPECT_EQ(32, TestObject::count); array = nullptr; EXPECT_EQ(0, TestObject::count); } TEST(Array, AraryBuilderAddAll) { { // Trivial case. char text[] = "foo"; ArrayBuilder builder = heapArrayBuilder(5); builder.add('<'); builder.addAll(text, text + 3); builder.add('>'); auto array = builder.finish(); EXPECT_EQ("", std::string(array.begin(), array.end())); } { // Trivial case, const. const char* text = "foo"; ArrayBuilder builder = heapArrayBuilder(5); builder.add('<'); builder.addAll(text, text + 3); builder.add('>'); auto array = builder.finish(); EXPECT_EQ("", std::string(array.begin(), array.end())); } { // Trivial case, non-pointer iterator. std::list text = {'f', 'o', 'o'}; ArrayBuilder builder = heapArrayBuilder(5); builder.add('<'); builder.addAll(text); builder.add('>'); auto array = builder.finish(); EXPECT_EQ("", std::string(array.begin(), array.end())); } { // Complex case. std::string strs[] = {"foo", "bar", "baz"}; ArrayBuilder builder = heapArrayBuilder(5); builder.add("qux"); builder.addAll(strs, strs + 3); builder.add("quux"); auto array = builder.finish(); EXPECT_EQ("qux", array[0]); EXPECT_EQ("foo", array[1]); EXPECT_EQ("bar", array[2]); EXPECT_EQ("baz", array[3]); EXPECT_EQ("quux", array[4]); } { // Complex case, noexcept. TestNoexceptObject::count = 0; TestNoexceptObject::copiedCount = 0; TestNoexceptObject objs[3]; EXPECT_EQ(3, TestNoexceptObject::count); EXPECT_EQ(0, TestNoexceptObject::copiedCount); ArrayBuilder builder = heapArrayBuilder(3); EXPECT_EQ(3, TestNoexceptObject::count); EXPECT_EQ(0, TestNoexceptObject::copiedCount); builder.addAll(objs, objs + 3); EXPECT_EQ(3, TestNoexceptObject::count); EXPECT_EQ(3, TestNoexceptObject::copiedCount); auto array = builder.finish(); EXPECT_EQ(3, TestNoexceptObject::count); EXPECT_EQ(3, TestNoexceptObject::copiedCount); } EXPECT_EQ(0, TestNoexceptObject::count); EXPECT_EQ(0, TestNoexceptObject::copiedCount); { // Complex case, exceptions possible. TestObject::count = 0; TestObject::copiedCount = 0; TestObject::throwAt = -1; TestObject objs[3]; EXPECT_EQ(3, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); ArrayBuilder builder = heapArrayBuilder(3); EXPECT_EQ(3, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); builder.addAll(objs, objs + 3); EXPECT_EQ(3, TestObject::count); EXPECT_EQ(3, TestObject::copiedCount); auto array = builder.finish(); EXPECT_EQ(3, TestObject::count); EXPECT_EQ(3, TestObject::copiedCount); } EXPECT_EQ(0, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); #if !KJ_NO_EXCEPTIONS { // Complex case, exceptions occur. TestObject::count = 0; TestObject::copiedCount = 0; TestObject::throwAt = -1; TestObject objs[3]; EXPECT_EQ(3, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); TestObject::throwAt = 1; ArrayBuilder builder = heapArrayBuilder(3); EXPECT_EQ(3, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); EXPECT_ANY_THROW(builder.addAll(objs, objs + 3)); TestObject::throwAt = -1; EXPECT_EQ(3, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); } EXPECT_EQ(0, TestObject::count); EXPECT_EQ(0, TestObject::copiedCount); #endif // !KJ_NO_EXCEPTIONS } TEST(Array, HeapCopy) { { Array copy = heapArray("foo", 3); EXPECT_EQ(3u, copy.size()); EXPECT_EQ("foo", std::string(copy.begin(), 3)); } { Array copy = heapArray(ArrayPtr("bar", 3)); EXPECT_EQ(3u, copy.size()); EXPECT_EQ("bar", std::string(copy.begin(), 3)); } { const char* ptr = "baz"; Array copy = heapArray(ptr, ptr + 3); EXPECT_EQ(3u, copy.size()); EXPECT_EQ("baz", std::string(copy.begin(), 3)); } } TEST(Array, OwnConst) { ArrayBuilder builder = heapArrayBuilder(2); int x[2] = {123, 234}; builder.addAll(x, x + 2); Array i = builder.finish(); //heapArray({123, 234}); ASSERT_EQ(2u, i.size()); EXPECT_EQ(123, i[0]); EXPECT_EQ(234, i[1]); Array ci = mv(i); ASSERT_EQ(2u, ci.size()); EXPECT_EQ(123, ci[0]); EXPECT_EQ(234, ci[1]); Array ci2 = heapArray({345, 456}); ASSERT_EQ(2u, ci2.size()); EXPECT_EQ(345, ci2[0]); EXPECT_EQ(456, ci2[1]); } TEST(Array, Map) { StringPtr foo = "abcd"; Array bar = KJ_MAP(c, foo) -> char { return c + 1; }; EXPECT_STREQ("bcde", str(bar).cStr()); } TEST(Array, MapRawArray) { uint foo[4] = {1, 2, 3, 4}; Array bar = KJ_MAP(i, foo) -> uint { return i * i; }; ASSERT_EQ(4, bar.size()); EXPECT_EQ(1, bar[0]); EXPECT_EQ(4, bar[1]); EXPECT_EQ(9, bar[2]); EXPECT_EQ(16, bar[3]); } TEST(Array, ReleaseAsBytesOrChars) { { Array chars = kj::heapArray("foo", 3); Array bytes = chars.releaseAsBytes(); EXPECT_TRUE(chars == nullptr); ASSERT_EQ(3, bytes.size()); EXPECT_EQ('f', bytes[0]); EXPECT_EQ('o', bytes[1]); EXPECT_EQ('o', bytes[2]); chars = bytes.releaseAsChars(); EXPECT_TRUE(bytes == nullptr); ASSERT_EQ(3, chars.size()); EXPECT_EQ('f', chars[0]); EXPECT_EQ('o', chars[1]); EXPECT_EQ('o', chars[2]); } { Array chars = kj::heapArray("foo", 3); Array bytes = chars.releaseAsBytes(); EXPECT_TRUE(chars == nullptr); ASSERT_EQ(3, bytes.size()); EXPECT_EQ('f', bytes[0]); EXPECT_EQ('o', bytes[1]); EXPECT_EQ('o', bytes[2]); chars = bytes.releaseAsChars(); EXPECT_TRUE(bytes == nullptr); ASSERT_EQ(3, chars.size()); EXPECT_EQ('f', chars[0]); EXPECT_EQ('o', chars[1]); EXPECT_EQ('o', chars[2]); } } #if KJ_CPP_STD > 201402L KJ_TEST("kj::arr()") { kj::Array array = kj::arr(kj::str("foo"), kj::str(123)); KJ_EXPECT(array == kj::ArrayPtr({"foo", "123"})); } struct ImmovableInt { ImmovableInt(int i): i(i) {} KJ_DISALLOW_COPY_AND_MOVE(ImmovableInt); int i; }; KJ_TEST("kj::arrOf()") { kj::Array array = kj::arrOf(123, 456, 789); KJ_ASSERT(array.size() == 3); KJ_EXPECT(array[0].i == 123); KJ_EXPECT(array[1].i == 456); KJ_EXPECT(array[2].i == 789); } #endif struct DestructionOrderRecorder { DestructionOrderRecorder(uint& counter, uint& recordTo) : counter(counter), recordTo(recordTo) {} ~DestructionOrderRecorder() { recordTo = ++counter; } uint& counter; uint& recordTo; }; TEST(Array, Attach) { uint counter = 0; uint destroyed1 = 0; uint destroyed2 = 0; uint destroyed3 = 0; auto obj1 = kj::heap(counter, destroyed1); auto obj2 = kj::heap(counter, destroyed2); auto obj3 = kj::heap(counter, destroyed3); auto builder = kj::heapArrayBuilder>(1); builder.add(kj::mv(obj1)); auto arr = builder.finish(); auto ptr = arr.begin(); Array> combined = arr.attach(kj::mv(obj2), kj::mv(obj3)); KJ_EXPECT(combined.begin() == ptr); KJ_EXPECT(obj1.get() == nullptr); KJ_EXPECT(obj2.get() == nullptr); KJ_EXPECT(obj3.get() == nullptr); KJ_EXPECT(destroyed1 == 0); KJ_EXPECT(destroyed2 == 0); KJ_EXPECT(destroyed3 == 0); combined = nullptr; KJ_EXPECT(destroyed1 == 1, destroyed1); KJ_EXPECT(destroyed2 == 2, destroyed2); KJ_EXPECT(destroyed3 == 3, destroyed3); } TEST(Array, AttachNested) { uint counter = 0; uint destroyed1 = 0; uint destroyed2 = 0; uint destroyed3 = 0; auto obj1 = kj::heap(counter, destroyed1); auto obj2 = kj::heap(counter, destroyed2); auto obj3 = kj::heap(counter, destroyed3); auto builder = kj::heapArrayBuilder>(1); builder.add(kj::mv(obj1)); auto arr = builder.finish(); auto ptr = arr.begin(); Array> combined = arr.attach(kj::mv(obj2)).attach(kj::mv(obj3)); KJ_EXPECT(combined.begin() == ptr); KJ_EXPECT(combined.size() == 1); KJ_EXPECT(obj1.get() == nullptr); KJ_EXPECT(obj2.get() == nullptr); KJ_EXPECT(obj3.get() == nullptr); KJ_EXPECT(destroyed1 == 0); KJ_EXPECT(destroyed2 == 0); KJ_EXPECT(destroyed3 == 0); combined = nullptr; KJ_EXPECT(destroyed1 == 1, destroyed1); KJ_EXPECT(destroyed2 == 2, destroyed2); KJ_EXPECT(destroyed3 == 3, destroyed3); } TEST(Array, AttachFromArrayPtr) { uint counter = 0; uint destroyed1 = 0; uint destroyed2 = 0; uint destroyed3 = 0; auto obj1 = kj::heap(counter, destroyed1); auto obj2 = kj::heap(counter, destroyed2); auto obj3 = kj::heap(counter, destroyed3); auto builder = kj::heapArrayBuilder>(1); builder.add(kj::mv(obj1)); auto arr = builder.finish(); auto ptr = arr.begin(); Array> combined = arr.asPtr().attach(kj::mv(obj2)).attach(kj::mv(obj3)); KJ_EXPECT(arr != nullptr); KJ_EXPECT(combined.begin() == ptr); KJ_EXPECT(obj1.get() == nullptr); KJ_EXPECT(obj2.get() == nullptr); KJ_EXPECT(obj3.get() == nullptr); KJ_EXPECT(destroyed1 == 0); KJ_EXPECT(destroyed2 == 0); KJ_EXPECT(destroyed3 == 0); combined = nullptr; KJ_EXPECT(destroyed2 == 1, destroyed2); KJ_EXPECT(destroyed3 == 2, destroyed3); arr = nullptr; KJ_EXPECT(destroyed1 == 3, destroyed1); } } // namespace } // namespace kj capnproto-c++-1.1.0/src/kj/table-test.c++0000644000175000017500000011700514712011043020470 0ustar00kentonkenton00000000000000// Copyright (c) 2018 Kenton Varda and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "table.h" #include #include #include #include "hash.h" #include "time.h" #include namespace kj { namespace _ { namespace { #if defined(KJ_DEBUG) && !__OPTIMIZE__ static constexpr uint MEDIUM_PRIME = 619; static constexpr uint BIG_PRIME = 6143; #else static constexpr uint MEDIUM_PRIME = 6143; static constexpr uint BIG_PRIME = 101363; #endif // Some of the tests build large tables. These numbers are used as the table sizes. We use primes // to avoid any unintended aliasing affects -- this is probably just paranoia, but why not? // // We use smaller values for debug builds to keep runtime down. KJ_TEST("_::tryReserveSize() works") { { Vector vec; tryReserveSize(vec, "foo"_kj); KJ_EXPECT(vec.capacity() == 4); // Vectors always grow by powers of two. } { Vector vec; tryReserveSize(vec, 123); KJ_EXPECT(vec.capacity() == 0); } } class StringHasher { public: StringPtr keyForRow(StringPtr s) const { return s; } bool matches(StringPtr a, StringPtr b) const { return a == b; } uint hashCode(StringPtr str) const { return kj::hashCode(str); } }; KJ_TEST("simple table") { Table> table; KJ_EXPECT(table.find("foo") == nullptr); KJ_EXPECT(table.size() == 0); KJ_EXPECT(table.insert("foo") == "foo"); KJ_EXPECT(table.size() == 1); KJ_EXPECT(table.insert("bar") == "bar"); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("foo")) == "foo"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(table.find("fop") == nullptr); KJ_EXPECT(table.find("baq") == nullptr); { StringPtr& ref = table.insert("baz"); KJ_EXPECT(ref == "baz"); StringPtr& ref2 = KJ_ASSERT_NONNULL(table.find("baz")); KJ_EXPECT(&ref == &ref2); } KJ_EXPECT(table.size() == 3); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "foo"); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(iter == table.end()); } KJ_EXPECT(table.eraseMatch("foo")); KJ_EXPECT(table.size() == 2); KJ_EXPECT(table.find("foo") == nullptr); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("baz")) == "baz"); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(iter == table.end()); } { auto& row = table.upsert("qux", [&](StringPtr&, StringPtr&&) { KJ_FAIL_ASSERT("shouldn't get here"); }); auto copy = kj::str("qux"); table.upsert(StringPtr(copy), [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(param.begin() == copy.begin()); KJ_EXPECT(&existing == &row); }); auto& found = KJ_ASSERT_NONNULL(table.find("qux")); KJ_EXPECT(&found == &row); } StringPtr STRS[] = { "corge"_kj, "grault"_kj, "garply"_kj }; table.insertAll(ArrayPtr(STRS)); KJ_EXPECT(table.size() == 6); KJ_EXPECT(table.find("corge") != nullptr); KJ_EXPECT(table.find("grault") != nullptr); KJ_EXPECT(table.find("garply") != nullptr); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.insert("bar")); KJ_EXPECT(table.size() == 6); KJ_EXPECT(table.insert("baa") == "baa"); KJ_EXPECT(table.eraseAll([](StringPtr s) { return s.startsWith("ba"); }) == 3); KJ_EXPECT(table.size() == 4); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(iter == table.end()); } auto& graultRow = table.begin()[1]; kj::StringPtr origGrault = graultRow; KJ_EXPECT(&table.findOrCreate("grault", [&]() -> kj::StringPtr { KJ_FAIL_ASSERT("shouldn't have called this"); }) == &graultRow); KJ_EXPECT(graultRow.begin() == origGrault.begin()); KJ_EXPECT(&KJ_ASSERT_NONNULL(table.find("grault")) == &graultRow); KJ_EXPECT(table.find("waldo") == nullptr); KJ_EXPECT(table.size() == 4); kj::String searchWaldo = kj::str("waldo"); kj::String insertWaldo = kj::str("waldo"); auto& waldo = table.findOrCreate(searchWaldo, [&]() -> kj::StringPtr { return insertWaldo; }); KJ_EXPECT(waldo == "waldo"); KJ_EXPECT(waldo.begin() == insertWaldo.begin()); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("grault")) == "grault"); KJ_EXPECT(&KJ_ASSERT_NONNULL(table.find("waldo")) == &waldo); KJ_EXPECT(table.size() == 5); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(*iter++ == "waldo"); KJ_EXPECT(iter == table.end()); } } class BadHasher { // String hash that always returns the same hash code. This should not affect correctness, only // performance. public: StringPtr keyForRow(StringPtr s) const { return s; } bool matches(StringPtr a, StringPtr b) const { return a == b; } uint hashCode(StringPtr str) const { return 1234; } }; KJ_TEST("hash tables when hash is always same") { Table> table; KJ_EXPECT(table.size() == 0); KJ_EXPECT(table.insert("foo") == "foo"); KJ_EXPECT(table.size() == 1); KJ_EXPECT(table.insert("bar") == "bar"); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("foo")) == "foo"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(table.find("fop") == nullptr); KJ_EXPECT(table.find("baq") == nullptr); { StringPtr& ref = table.insert("baz"); KJ_EXPECT(ref == "baz"); StringPtr& ref2 = KJ_ASSERT_NONNULL(table.find("baz")); KJ_EXPECT(&ref == &ref2); } KJ_EXPECT(table.size() == 3); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "foo"); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(iter == table.end()); } KJ_EXPECT(table.eraseMatch("foo")); KJ_EXPECT(table.size() == 2); KJ_EXPECT(table.find("foo") == nullptr); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("baz")) == "baz"); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(iter == table.end()); } { auto& row = table.upsert("qux", [&](StringPtr&, StringPtr&&) { KJ_FAIL_ASSERT("shouldn't get here"); }); auto copy = kj::str("qux"); table.upsert(StringPtr(copy), [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(param.begin() == copy.begin()); KJ_EXPECT(&existing == &row); }); auto& found = KJ_ASSERT_NONNULL(table.find("qux")); KJ_EXPECT(&found == &row); } StringPtr STRS[] = { "corge"_kj, "grault"_kj, "garply"_kj }; table.insertAll(ArrayPtr(STRS)); KJ_EXPECT(table.size() == 6); KJ_EXPECT(table.find("corge") != nullptr); KJ_EXPECT(table.find("grault") != nullptr); KJ_EXPECT(table.find("garply") != nullptr); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.insert("bar")); } class IntHasher { // Dumb integer hasher that just returns the integer itself. public: uint keyForRow(uint i) const { return i; } bool matches(uint a, uint b) const { return a == b; } uint hashCode(uint i) const { return i; } }; KJ_TEST("HashIndex with many erasures doesn't keep growing") { HashIndex index; kj::ArrayPtr rows = nullptr; for (uint i: kj::zeroTo(1000000)) { KJ_ASSERT(index.insert(rows, 0, i) == nullptr); index.erase(rows, 0, i); } KJ_ASSERT(index.capacity() < 10); } struct SiPair { kj::StringPtr str; uint i; inline bool operator==(SiPair other) const { return str == other.str && i == other.i; } }; class SiPairStringHasher { public: StringPtr keyForRow(SiPair s) const { return s.str; } bool matches(SiPair a, StringPtr b) const { return a.str == b; } uint hashCode(StringPtr str) const { return inner.hashCode(str); } private: StringHasher inner; }; class SiPairIntHasher { public: uint keyForRow(SiPair s) const { return s.i; } bool matches(SiPair a, uint b) const { return a.i == b; } uint hashCode(uint i) const { return i; } }; KJ_TEST("double-index table") { Table, HashIndex> table; KJ_EXPECT(table.size() == 0); KJ_EXPECT(table.insert({"foo", 123}) == (SiPair {"foo", 123})); KJ_EXPECT(table.size() == 1); KJ_EXPECT(table.insert({"bar", 456}) == (SiPair {"bar", 456})); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find>(123)) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(123)) == (SiPair {"foo", 123})); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.insert({"foo", 111})); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.insert({"qux", 123})); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(123)) == (SiPair {"foo", 123})); KJ_EXPECT( table.findOrCreate<0>("foo", []() -> SiPair { KJ_FAIL_ASSERT("shouldn't have called this"); }) == (SiPair {"foo", 123})); KJ_EXPECT(table.size() == 2); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.findOrCreate<0>("corge", []() -> SiPair { return {"corge", 123}; })); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(123)) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("bar")) == (SiPair {"bar", 456})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(456)) == (SiPair {"bar", 456})); KJ_EXPECT(table.find<0>("corge") == nullptr); KJ_EXPECT( table.findOrCreate<0>("corge", []() -> SiPair { return {"corge", 789}; }) == (SiPair {"corge", 789})); KJ_EXPECT(table.size() == 3); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(123)) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("bar")) == (SiPair {"bar", 456})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(456)) == (SiPair {"bar", 456})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("corge")) == (SiPair {"corge", 789})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(789)) == (SiPair {"corge", 789})); KJ_EXPECT( table.findOrCreate<1>(234, []() -> SiPair { return {"grault", 234}; }) == (SiPair {"grault", 234})); KJ_EXPECT(table.size() == 4); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("foo")) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(123)) == (SiPair {"foo", 123})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("bar")) == (SiPair {"bar", 456})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(456)) == (SiPair {"bar", 456})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("corge")) == (SiPair {"corge", 789})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(789)) == (SiPair {"corge", 789})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<0>("grault")) == (SiPair {"grault", 234})); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find<1>(234)) == (SiPair {"grault", 234})); } class UintHasher { public: uint keyForRow(uint i) const { return i; } bool matches(uint a, uint b) const { return a == b; } uint hashCode(uint i) const { return i; } }; KJ_TEST("benchmark: kj::Table") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; for (auto step: STEP) { KJ_CONTEXT(step); Table> table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(j * 5 + 123); } for (uint i: kj::zeroTo(SOME_PRIME)) { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(table.find(i * 5 + 122) == nullptr); KJ_ASSERT(table.find(i * 5 + 124) == nullptr); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { table.erase(KJ_ASSERT_NONNULL(table.find(i * 5 + 123))); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(i * 5 + 123) == nullptr); } else { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); } } } } KJ_TEST("benchmark: std::unordered_set") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; for (auto step: STEP) { KJ_CONTEXT(step); std::unordered_set table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(j * 5 + 123); } for (uint i: kj::zeroTo(SOME_PRIME)) { auto iter = table.find(i * 5 + 123); KJ_ASSERT(iter != table.end()); uint value = *iter; KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(table.find(i * 5 + 122) == table.end()); KJ_ASSERT(table.find(i * 5 + 124) == table.end()); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { KJ_ASSERT(table.erase(i * 5 + 123) > 0); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(i * 5 + 123) == table.end()); } else { auto iter = table.find(i * 5 + 123); KJ_ASSERT(iter != table.end()); uint value = *iter; KJ_ASSERT(value == i * 5 + 123); } } } } KJ_TEST("benchmark: kj::Table") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; kj::Vector strings(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { strings.add(kj::str(i * 5 + 123)); } for (auto step: STEP) { KJ_CONTEXT(step); Table> table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(strings[j]); } for (uint i: kj::zeroTo(SOME_PRIME)) { StringPtr value = KJ_ASSERT_NONNULL(table.find(strings[i])); KJ_ASSERT(value == strings[i]); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { table.erase(KJ_ASSERT_NONNULL(table.find(strings[i]))); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(strings[i]) == nullptr); } else { StringPtr value = KJ_ASSERT_NONNULL(table.find(strings[i])); KJ_ASSERT(value == strings[i]); } } } } struct StlStringHash { inline size_t operator()(StringPtr str) const { return kj::hashCode(str); } }; KJ_TEST("benchmark: std::unordered_set") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; kj::Vector strings(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { strings.add(kj::str(i * 5 + 123)); } for (auto step: STEP) { KJ_CONTEXT(step); std::unordered_set table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(strings[j]); } for (uint i: kj::zeroTo(SOME_PRIME)) { auto iter = table.find(strings[i]); KJ_ASSERT(iter != table.end()); StringPtr value = *iter; KJ_ASSERT(value == strings[i]); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { KJ_ASSERT(table.erase(strings[i]) > 0); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(strings[i]) == table.end()); } else { auto iter = table.find(strings[i]); KJ_ASSERT(iter != table.end()); StringPtr value = *iter; KJ_ASSERT(value == strings[i]); } } } } // ======================================================================================= KJ_TEST("B-tree internals") { { BTreeImpl::Leaf leaf; memset(&leaf, 0, sizeof(leaf)); for (auto i: kj::indices(leaf.rows)) { KJ_CONTEXT(i); KJ_EXPECT(leaf.size() == i); if (i < kj::size(leaf.rows) / 2) { #ifdef KJ_DEBUG KJ_EXPECT_THROW(FAILED, leaf.isHalfFull()); #endif KJ_EXPECT(!leaf.isMostlyFull()); } if (i == kj::size(leaf.rows) / 2) { KJ_EXPECT(leaf.isHalfFull()); KJ_EXPECT(!leaf.isMostlyFull()); } if (i > kj::size(leaf.rows) / 2) { KJ_EXPECT(!leaf.isHalfFull()); KJ_EXPECT(leaf.isMostlyFull()); } if (i == kj::size(leaf.rows)) { KJ_EXPECT(leaf.isFull()); } else { KJ_EXPECT(!leaf.isFull()); } leaf.rows[i] = 1; } KJ_EXPECT(leaf.size() == kj::size(leaf.rows)); } { BTreeImpl::Parent parent; memset(&parent, 0, sizeof(parent)); for (auto i: kj::indices(parent.keys)) { KJ_CONTEXT(i); KJ_EXPECT(parent.keyCount() == i); if (i < kj::size(parent.keys) / 2) { #ifdef KJ_DEBUG KJ_EXPECT_THROW(FAILED, parent.isHalfFull()); #endif KJ_EXPECT(!parent.isMostlyFull()); } if (i == kj::size(parent.keys) / 2) { KJ_EXPECT(parent.isHalfFull()); KJ_EXPECT(!parent.isMostlyFull()); } if (i > kj::size(parent.keys) / 2) { KJ_EXPECT(!parent.isHalfFull()); KJ_EXPECT(parent.isMostlyFull()); } if (i == kj::size(parent.keys)) { KJ_EXPECT(parent.isFull()); } else { KJ_EXPECT(!parent.isFull()); } parent.keys[i] = 1; } KJ_EXPECT(parent.keyCount() == kj::size(parent.keys)); } } class StringCompare { public: StringPtr keyForRow(StringPtr s) const { return s; } bool isBefore(StringPtr a, StringPtr b) const { return a < b; } bool matches(StringPtr a, StringPtr b) const { return a == b; } }; KJ_TEST("simple tree table") { Table> table; KJ_EXPECT(table.find("foo") == nullptr); KJ_EXPECT(table.size() == 0); KJ_EXPECT(table.insert("foo") == "foo"); KJ_EXPECT(table.size() == 1); KJ_EXPECT(table.insert("bar") == "bar"); KJ_EXPECT(table.size() == 2); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("foo")) == "foo"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(table.find("fop") == nullptr); KJ_EXPECT(table.find("baq") == nullptr); { StringPtr& ref = table.insert("baz"); KJ_EXPECT(ref == "baz"); StringPtr& ref2 = KJ_ASSERT_NONNULL(table.find("baz")); KJ_EXPECT(&ref == &ref2); } KJ_EXPECT(table.size() == 3); { auto range = table.ordered(); auto iter = range.begin(); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(*iter++ == "foo"); KJ_EXPECT(iter == range.end()); } KJ_EXPECT(table.eraseMatch("foo")); KJ_EXPECT(table.size() == 2); KJ_EXPECT(table.find("foo") == nullptr); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("bar")) == "bar"); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("baz")) == "baz"); { auto range = table.ordered(); auto iter = range.begin(); KJ_EXPECT(*iter++ == "bar"); KJ_EXPECT(*iter++ == "baz"); KJ_EXPECT(iter == range.end()); } { auto& row = table.upsert("qux", [&](StringPtr&, StringPtr&&) { KJ_FAIL_ASSERT("shouldn't get here"); }); auto copy = kj::str("qux"); table.upsert(StringPtr(copy), [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(param.begin() == copy.begin()); KJ_EXPECT(&existing == &row); }); auto& found = KJ_ASSERT_NONNULL(table.find("qux")); KJ_EXPECT(&found == &row); } StringPtr STRS[] = { "corge"_kj, "grault"_kj, "garply"_kj }; table.insertAll(ArrayPtr(STRS)); KJ_EXPECT(table.size() == 6); KJ_EXPECT(table.find("corge") != nullptr); KJ_EXPECT(table.find("grault") != nullptr); KJ_EXPECT(table.find("garply") != nullptr); KJ_EXPECT_THROW_MESSAGE("inserted row already exists in table", table.insert("bar")); KJ_EXPECT(table.size() == 6); KJ_EXPECT(table.insert("baa") == "baa"); KJ_EXPECT(table.eraseAll([](StringPtr s) { return s.startsWith("ba"); }) == 3); KJ_EXPECT(table.size() == 4); { auto range = table.ordered(); auto iter = range.begin(); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(iter == range.end()); } { auto range = table.range("foo", "har"); auto iter = range.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(iter == range.end()); } { auto range = table.range("garply", "grault"); auto iter = range.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(iter == range.end()); } { auto iter = table.seek("garply"); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(iter == table.ordered().end()); } { auto iter = table.seek("gorply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(iter == table.ordered().end()); } auto& graultRow = table.begin()[1]; kj::StringPtr origGrault = graultRow; KJ_EXPECT(&table.findOrCreate("grault", [&]() -> kj::StringPtr { KJ_FAIL_ASSERT("shouldn't have called this"); }) == &graultRow); KJ_EXPECT(graultRow.begin() == origGrault.begin()); KJ_EXPECT(&KJ_ASSERT_NONNULL(table.find("grault")) == &graultRow); KJ_EXPECT(table.find("waldo") == nullptr); KJ_EXPECT(table.size() == 4); kj::String searchWaldo = kj::str("waldo"); kj::String insertWaldo = kj::str("waldo"); auto& waldo = table.findOrCreate(searchWaldo, [&]() -> kj::StringPtr { return insertWaldo; }); KJ_EXPECT(waldo == "waldo"); KJ_EXPECT(waldo.begin() == insertWaldo.begin()); KJ_EXPECT(KJ_ASSERT_NONNULL(table.find("grault")) == "grault"); KJ_EXPECT(&KJ_ASSERT_NONNULL(table.find("waldo")) == &waldo); KJ_EXPECT(table.size() == 5); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(*iter++ == "waldo"); KJ_EXPECT(iter == table.end()); } // Verify that move constructor/assignment work. Table> other(kj::mv(table)); KJ_EXPECT(other.size() == 5); KJ_EXPECT(table.size() == 0); KJ_EXPECT(table.begin() == table.end()); { auto iter = other.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(*iter++ == "waldo"); KJ_EXPECT(iter == other.end()); } table = kj::mv(other); KJ_EXPECT(other.size() == 0); KJ_EXPECT(table.size() == 5); { auto iter = table.begin(); KJ_EXPECT(*iter++ == "garply"); KJ_EXPECT(*iter++ == "grault"); KJ_EXPECT(*iter++ == "qux"); KJ_EXPECT(*iter++ == "corge"); KJ_EXPECT(*iter++ == "waldo"); KJ_EXPECT(iter == table.end()); } KJ_EXPECT(other.begin() == other.end()); } class UintCompare { public: uint keyForRow(uint i) const { return i; } bool isBefore(uint a, uint b) const { return a < b; } bool matches(uint a, uint b) const { return a == b; } }; KJ_TEST("large tree table") { constexpr uint SOME_PRIME = MEDIUM_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; for (auto step: STEP) { KJ_CONTEXT(step); Table> table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(j * 5 + 123); } for (uint i: kj::zeroTo(SOME_PRIME)) { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(table.find(i * 5 + 122) == nullptr); KJ_ASSERT(table.find(i * 5 + 124) == nullptr); } table.verify(); { auto range = table.ordered(); auto iter = range.begin(); for (uint i: kj::zeroTo(SOME_PRIME)) { KJ_ASSERT(*iter++ == i * 5 + 123); } KJ_ASSERT(iter == range.end()); } for (uint i: kj::zeroTo(SOME_PRIME)) { KJ_CONTEXT(i); if (i % 2 == 0 || i % 7 == 0) { table.erase(KJ_ASSERT_NONNULL(table.find(i * 5 + 123), i)); table.verify(); } } { auto range = table.ordered(); auto iter = range.begin(); for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(i * 5 + 123) == nullptr); } else { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(*iter++ == i * 5 + 123); } } KJ_ASSERT(iter == range.end()); } } } KJ_TEST("TreeIndex fuzz test") { // A test which randomly modifies a TreeIndex to try to discover buggy state changes. uint seed = (kj::systemPreciseCalendarClock().now() - kj::UNIX_EPOCH) / kj::NANOSECONDS; KJ_CONTEXT(seed); // print the seed if the test fails srand(seed); Table> table; auto randomInsert = [&]() { table.upsert(rand(), [](auto&&, auto&&) {}); }; auto randomErase = [&]() { if (table.size() > 0) { auto& row = table.begin()[rand() % table.size()]; table.erase(row); } }; auto randomLookup = [&]() { if (table.size() > 0) { auto& row = table.begin()[rand() % table.size()]; auto& found = KJ_ASSERT_NONNULL(table.find(row)); KJ_ASSERT(&found == &row); } }; // First pass: focus on insertions, aim to do 2x as many insertions as deletions. for (auto i KJ_UNUSED: kj::zeroTo(1000)) { switch (rand() % 4) { case 0: case 1: randomInsert(); break; case 2: randomErase(); break; case 3: randomLookup(); break; } table.verify(); } // Second pass: focus on deletions, aim to do 2x as many deletions as insertions. for (auto i KJ_UNUSED: kj::zeroTo(1000)) { switch (rand() % 4) { case 0: randomInsert(); break; case 1: case 2: randomErase(); break; case 3: randomLookup(); break; } table.verify(); } } KJ_TEST("TreeIndex clear() leaves tree in valid state") { // A test which ensures that calling clear() does not break the internal state of a TreeIndex. // It used to be the case that clearing a non-empty tree would leave it thinking that it had room // for one more node than it really did, causing it to write and read beyond the end of its // internal array of nodes. Table> table; // Insert at least one value to allocate an initial set of tree nodes. table.upsert(1, [](auto&&, auto&&) {}); KJ_EXPECT(table.find(1) != nullptr); table.clear(); // Insert enough values to force writes/reads beyond the end of the tree's internal node array. for (uint i = 0; i < 29; ++i) { table.upsert(i, [](auto&&, auto&&) {}); } for (uint i = 0; i < 29; ++i) { KJ_EXPECT(table.find(i) != nullptr); } } KJ_TEST("benchmark: kj::Table") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; for (auto step: STEP) { KJ_CONTEXT(step); Table> table; table.reserve(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(j * 5 + 123); } for (uint i: kj::zeroTo(SOME_PRIME)) { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(table.find(i * 5 + 122) == nullptr); KJ_ASSERT(table.find(i * 5 + 124) == nullptr); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { table.erase(KJ_ASSERT_NONNULL(table.find(i * 5 + 123))); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(i * 5 + 123) == nullptr); } else { uint value = KJ_ASSERT_NONNULL(table.find(i * 5 + 123)); KJ_ASSERT(value == i * 5 + 123); } } } } KJ_TEST("benchmark: std::set") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; for (auto step: STEP) { KJ_CONTEXT(step); std::set table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(j * 5 + 123); } for (uint i: kj::zeroTo(SOME_PRIME)) { auto iter = table.find(i * 5 + 123); KJ_ASSERT(iter != table.end()); uint value = *iter; KJ_ASSERT(value == i * 5 + 123); KJ_ASSERT(table.find(i * 5 + 122) == table.end()); KJ_ASSERT(table.find(i * 5 + 124) == table.end()); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { KJ_ASSERT(table.erase(i * 5 + 123) > 0); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(i * 5 + 123) == table.end()); } else { auto iter = table.find(i * 5 + 123); KJ_ASSERT(iter != table.end()); uint value = *iter; KJ_ASSERT(value == i * 5 + 123); } } } } KJ_TEST("benchmark: kj::Table") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; kj::Vector strings(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { strings.add(kj::str(i * 5 + 123)); } for (auto step: STEP) { KJ_CONTEXT(step); Table> table; table.reserve(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(strings[j]); } for (uint i: kj::zeroTo(SOME_PRIME)) { StringPtr value = KJ_ASSERT_NONNULL(table.find(strings[i])); KJ_ASSERT(value == strings[i]); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { table.erase(KJ_ASSERT_NONNULL(table.find(strings[i]))); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(strings[i]) == nullptr); } else { auto& value = KJ_ASSERT_NONNULL(table.find(strings[i])); KJ_ASSERT(value == strings[i]); } } } } KJ_TEST("benchmark: std::set") { constexpr uint SOME_PRIME = BIG_PRIME; constexpr uint STEP[] = {1, 2, 4, 7, 43, 127}; kj::Vector strings(SOME_PRIME); for (uint i: kj::zeroTo(SOME_PRIME)) { strings.add(kj::str(i * 5 + 123)); } for (auto step: STEP) { KJ_CONTEXT(step); std::set table; for (uint i: kj::zeroTo(SOME_PRIME)) { uint j = (i * step) % SOME_PRIME; table.insert(strings[j]); } for (uint i: kj::zeroTo(SOME_PRIME)) { auto iter = table.find(strings[i]); KJ_ASSERT(iter != table.end()); StringPtr value = *iter; KJ_ASSERT(value == strings[i]); } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { KJ_ASSERT(table.erase(strings[i]) > 0); } } for (uint i: kj::zeroTo(SOME_PRIME)) { if (i % 2 == 0 || i % 7 == 0) { // erased KJ_ASSERT(table.find(strings[i]) == table.end()); } else { auto iter = table.find(strings[i]); KJ_ASSERT(iter != table.end()); StringPtr value = *iter; KJ_ASSERT(value == strings[i]); } } } } // ======================================================================================= KJ_TEST("insertion order index") { Table table; { auto range = table.ordered(); KJ_EXPECT(range.begin() == range.end()); } table.insert(12); table.insert(34); table.insert(56); table.insert(78); { auto range = table.ordered(); auto iter = range.begin(); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 12); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 34); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 56); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 78); KJ_EXPECT(iter == range.end()); KJ_EXPECT(*--iter == 78); KJ_EXPECT(*--iter == 56); KJ_EXPECT(*--iter == 34); KJ_EXPECT(*--iter == 12); KJ_EXPECT(iter == range.begin()); } table.erase(table.begin()[1]); { auto range = table.ordered(); auto iter = range.begin(); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 12); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 56); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 78); KJ_EXPECT(iter == range.end()); KJ_EXPECT(*--iter == 78); KJ_EXPECT(*--iter == 56); KJ_EXPECT(*--iter == 12); KJ_EXPECT(iter == range.begin()); } // Allocate enough more elements to cause a resize. table.insert(111); table.insert(222); table.insert(333); table.insert(444); table.insert(555); table.insert(666); table.insert(777); table.insert(888); table.insert(999); { auto range = table.ordered(); auto iter = range.begin(); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 12); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 56); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 78); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 111); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 222); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 333); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 444); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 555); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 666); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 777); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 888); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 999); KJ_EXPECT(iter == range.end()); } // Remove everything. while (table.size() > 0) { table.erase(*table.begin()); } { auto range = table.ordered(); KJ_EXPECT(range.begin() == range.end()); } } KJ_TEST("insertion order index is movable") { using UintTable = Table; kj::Maybe myTable; { UintTable yourTable; yourTable.insert(12); yourTable.insert(34); yourTable.insert(56); yourTable.insert(78); yourTable.insert(111); yourTable.insert(222); yourTable.insert(333); yourTable.insert(444); yourTable.insert(555); yourTable.insert(666); yourTable.insert(777); yourTable.insert(888); yourTable.insert(999); myTable = kj::mv(yourTable); } auto& table = KJ_ASSERT_NONNULL(myTable); // At one time the following induced a segfault/double-free, due to incorrect memory management in // InsertionOrderIndex's move ctor and dtor. auto range = table.ordered(); auto iter = range.begin(); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 12); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 34); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 56); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 78); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 111); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 222); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 333); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 444); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 555); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 666); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 777); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 888); KJ_ASSERT(iter != range.end()); KJ_EXPECT(*iter++ == 999); KJ_EXPECT(iter == range.end()); } // ======================================================================================= // Test bug where insertion failure on a later index in the table would not be rolled back // correctly if a previous index was TreeIndex. class StringLengthCompare { // Considers two strings equal if they have the same length. public: inline size_t keyForRow(StringPtr entry) const { return entry.size(); } inline bool matches(StringPtr e, size_t key) const { return e.size() == key; } inline bool isBefore(StringPtr e, size_t key) const { return e.size() < key; } uint hashCode(size_t size) const { return size; } }; KJ_TEST("HashIndex rollback on insertion failure") { // Test that when an insertion produces a duplicate on a later index, changes to previous indexes // are properly rolled back. Table, HashIndex> table; table.insert("a"_kj); table.insert("ab"_kj); table.insert("abc"_kj); { // We use upsert() so that we don't throw an exception from the duplicate, but this exercises // the same logic as a duplicate insert() other than throwing. kj::StringPtr& found = table.upsert("xyz"_kj, [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(existing == "abc"); KJ_EXPECT(param == "xyz"); }); KJ_EXPECT(found == "abc"); table.erase(found); } table.insert("xyz"_kj); { kj::StringPtr& found = table.upsert("tuv"_kj, [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(existing == "xyz"); KJ_EXPECT(param == "tuv"); }); KJ_EXPECT(found == "xyz"); } } KJ_TEST("TreeIndex rollback on insertion failure") { // Test that when an insertion produces a duplicate on a later index, changes to previous indexes // are properly rolled back. Table, TreeIndex> table; table.insert("a"_kj); table.insert("ab"_kj); table.insert("abc"_kj); { // We use upsert() so that we don't throw an exception from the duplicate, but this exercises // the same logic as a duplicate insert() other than throwing. kj::StringPtr& found = table.upsert("xyz"_kj, [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(existing == "abc"); KJ_EXPECT(param == "xyz"); }); KJ_EXPECT(found == "abc"); table.erase(found); } table.insert("xyz"_kj); { kj::StringPtr& found = table.upsert("tuv"_kj, [&](StringPtr& existing, StringPtr&& param) { KJ_EXPECT(existing == "xyz"); KJ_EXPECT(param == "tuv"); }); KJ_EXPECT(found == "xyz"); } } } // namespace } // namespace _ } // namespace kj capnproto-c++-1.1.0/src/kj/CMakeLists.txt0000644000175000017500000002064114712011043020671 0ustar00kentonkenton00000000000000 # kj =========================================================================== set(kj_sources_lite array.c++ cidr.c++ list.c++ common.c++ debug.c++ exception.c++ io.c++ memory.c++ mutex.c++ string.c++ source-location.c++ hash.c++ table.c++ thread.c++ main.c++ arena.c++ test-helpers.c++ units.c++ encoding.c++ ) set(kj_sources_heavy refcount.c++ string-tree.c++ time.c++ filesystem.c++ filesystem-disk-unix.c++ filesystem-disk-win32.c++ parse/char.c++ ) if(NOT CAPNP_LITE) set(kj_sources ${kj_sources_lite} ${kj_sources_heavy}) else() set(kj_sources ${kj_sources_lite}) endif() set(kj_headers cidr.h common.h units.h memory.h refcount.h array.h list.h vector.h string.h string-tree.h source-location.h hash.h table.h map.h encoding.h exception.h debug.h arena.h io.h tuple.h one-of.h function.h mutex.h thread.h threadlocal.h filesystem.h time.h main.h win32-api-version.h windows-sanity.h ) set(kj-parse_headers parse/common.h parse/char.h ) set(kj-std_headers std/iostream.h ) add_library(kj ${kj_sources}) add_library(CapnProto::kj ALIAS kj) # TODO(cleanup): Use cxx_std_14 once it's safe to require cmake 3.8. target_compile_features(kj PUBLIC cxx_generic_lambdas) if(UNIX AND NOT ANDROID) target_link_libraries(kj PUBLIC pthread) endif() #make sure the lite flag propagates to all users (internal + external) of this library target_compile_definitions(kj PUBLIC ${CAPNP_LITE_FLAG}) #make sure external consumers don't need to manually set the include dirs get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) target_include_directories(kj PUBLIC $ $ ) # Ensure the library has a version set to match autotools build set_target_properties(kj PROPERTIES VERSION ${VERSION}) install(TARGETS kj ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj") install(FILES ${kj-parse_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/parse") install(FILES ${kj-std_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/std") set(kj-test_sources test.c++ ) set(kj-test_headers test.h ) set(kj-test-compat_headers compat/gtest.h ) add_library(kj-test ${kj-test_sources}) add_library(CapnProto::kj-test ALIAS kj-test) target_link_libraries(kj-test PUBLIC kj) # Ensure the library has a version set to match autotools build set_target_properties(kj-test PROPERTIES VERSION ${VERSION}) install(TARGETS kj-test ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj-test_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj") install(FILES ${kj-test-compat_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/compat") set(kj-async_sources async.c++ async-unix.c++ async-win32.c++ async-io-win32.c++ async-io.c++ async-io-unix.c++ timer.c++ ) set(kj-async_headers async-prelude.h async.h async-inl.h async-unix.h async-win32.h async-io.h async-queue.h cidr.h timer.h ) if(NOT CAPNP_LITE) add_library(kj-async ${kj-async_sources}) add_library(CapnProto::kj-async ALIAS kj-async) target_link_libraries(kj-async PUBLIC kj) if(WITH_FIBERS) target_compile_definitions(kj-async PUBLIC KJ_USE_FIBERS) if(_WITH_LIBUCONTEXT) target_link_libraries(kj-async PUBLIC PkgConfig::libucontext) endif() else() target_compile_definitions(kj-async PUBLIC KJ_USE_FIBERS=0) endif() if(UNIX) # external clients of this library need to link to pthreads target_compile_options(kj-async INTERFACE "-pthread") elseif(WIN32) target_link_libraries(kj-async PUBLIC ws2_32) endif() # Ensure the library has a version set to match autotools build set_target_properties(kj-async PROPERTIES VERSION ${VERSION}) install(TARGETS kj-async ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj-async_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj") endif() # kj-http ====================================================================== set(kj-http_sources compat/url.c++ compat/http.c++ ) set(kj-http_headers compat/url.h compat/http.h ) if(NOT CAPNP_LITE) add_library(kj-http ${kj-http_sources}) add_library(CapnProto::kj-http ALIAS kj-http) if(WITH_ZLIB) target_compile_definitions(kj-http PRIVATE KJ_HAS_ZLIB) target_link_libraries(kj-http PUBLIC kj-async kj ZLIB::ZLIB) else() target_link_libraries(kj-http PUBLIC kj-async kj) endif() # Ensure the library has a version set to match autotools build set_target_properties(kj-http PROPERTIES VERSION ${VERSION}) install(TARGETS kj-http ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj-http_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/compat") endif() # kj-tls ====================================================================== if(WITH_OPENSSL) set(kj-tls_sources compat/readiness-io.c++ compat/tls.c++ ) set(kj-tls_headers compat/readiness-io.h compat/tls.h ) if(NOT CAPNP_LITE) add_library(kj-tls ${kj-tls_sources}) add_library(CapnProto::kj-tls ALIAS kj-tls) target_link_libraries(kj-tls PUBLIC kj-async) target_compile_definitions(kj-tls PRIVATE KJ_HAS_OPENSSL) target_link_libraries(kj-tls PRIVATE OpenSSL::SSL OpenSSL::Crypto) # Ensure the library has a version set to match autotools build set_target_properties(kj-tls PROPERTIES VERSION ${VERSION}) install(TARGETS kj-tls ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj-tls_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/compat") endif() endif() # kj-gzip ====================================================================== if(WITH_ZLIB) set(kj-gzip_sources compat/gzip.c++ ) set(kj-gzip_headers compat/gzip.h ) if(NOT CAPNP_LITE) add_library(kj-gzip ${kj-gzip_sources}) add_library(CapnProto::kj-gzip ALIAS kj-gzip) target_compile_definitions(kj-gzip PRIVATE KJ_HAS_ZLIB) target_link_libraries(kj-gzip PUBLIC kj-async kj ZLIB::ZLIB) # Ensure the library has a version set to match autotools build set_target_properties(kj-gzip PROPERTIES VERSION ${VERSION}) install(TARGETS kj-gzip ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${kj-gzip_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kj/compat") endif() endif() # Tests ======================================================================== if(BUILD_TESTING) add_executable(kj-tests common-test.c++ memory-test.c++ array-test.c++ list-test.c++ string-test.c++ table-test.c++ map-test.c++ exception-test.c++ # this test overrides symbolizer and has to be linked separately # exception-override-symbolizer-test.c++ debug-test.c++ io-test.c++ mutex-test.c++ time-test.c++ threadlocal-test.c++ test-test.c++ std/iostream-test.c++ ) # TODO: Link with librt on Solaris for sched_yield target_link_libraries(kj-tests kj-test kj) add_dependencies(check kj-tests) add_test(NAME kj-tests-run COMMAND kj-tests) if(NOT CAPNP_LITE) add_executable(kj-heavy-tests async-test.c++ async-xthread-test.c++ async-coroutine-test.c++ async-unix-test.c++ async-unix-xthread-test.c++ async-win32-test.c++ async-win32-xthread-test.c++ async-io-test.c++ async-queue-test.c++ refcount-test.c++ string-tree-test.c++ encoding-test.c++ arena-test.c++ units-test.c++ tuple-test.c++ one-of-test.c++ function-test.c++ filesystem-test.c++ filesystem-disk-test.c++ parse/common-test.c++ parse/char-test.c++ compat/url-test.c++ compat/http-test.c++ compat/gzip-test.c++ compat/tls-test.c++ ) target_link_libraries(kj-heavy-tests kj-http kj-async kj-test kj) if(WITH_OPENSSL) target_link_libraries(kj-heavy-tests kj-tls) # tls-test.c++ needs to use OpenSSL directly. target_link_libraries(kj-heavy-tests OpenSSL::SSL OpenSSL::Crypto) target_compile_definitions(kj-heavy-tests PRIVATE KJ_HAS_OPENSSL) set_property( SOURCE compat/tls-test.c++ APPEND PROPERTY COMPILE_DEFINITIONS KJ_HAS_OPENSSL ) endif() if(WITH_ZLIB) target_link_libraries(kj-heavy-tests kj-gzip) set_property( SOURCE compat/gzip-test.c++ APPEND PROPERTY COMPILE_DEFINITIONS KJ_HAS_ZLIB ) endif() add_dependencies(check kj-heavy-tests) add_test(NAME kj-heavy-tests-run COMMAND kj-heavy-tests) endif() # NOT CAPNP_LITE endif() # BUILD_TESTING capnproto-c++-1.1.0/src/kj/encoding-test.c++0000644000175000017500000005077214712011043021176 0ustar00kentonkenton00000000000000// Copyright (c) 2017 Cloudflare, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "encoding.h" #include #include namespace kj { namespace { CappedArray hex(byte i) { return kj::hex((uint8_t )i); } CappedArray hex(char i) { return kj::hex((uint8_t )i); } #if __cpp_char8_t [[maybe_unused]] CappedArray hex(char8_t i) { return kj::hex((uint8_t )i); } #endif CappedArray hex(char16_t i) { return kj::hex((uint16_t)i); } CappedArray hex(char32_t i) { return kj::hex((uint32_t)i); } CappedArray hex(wchar_t i) { return kj::hex((uint32_t)i); } // Hexify chars correctly. // // TODO(cleanup): Should this go into string.h with the other definitions of hex()? template void expectResImpl(EncodingResult result, ArrayPtr expected, bool errors = false) { if (errors) { KJ_EXPECT(result.hadErrors); } else { KJ_EXPECT(!result.hadErrors); } KJ_EXPECT(result.size() == expected.size(), result.size(), expected.size()); for (auto i: kj::zeroTo(kj::min(result.size(), expected.size()))) { KJ_EXPECT(result[i] == expected[i], i, hex(result[i]), hex(expected[i])); } } template void expectRes(EncodingResult result, const U (&expected)[s], bool errors = false) { expectResImpl(kj::mv(result), arrayPtr(expected, s - 1), errors); } #if __cpp_char8_t template void expectRes(EncodingResult result, const char8_t (&expected)[s], bool errors = false) { expectResImpl(kj::mv(result), arrayPtr(reinterpret_cast(expected), s - 1), errors); } #endif template void expectRes(EncodingResult result, byte (&expected)[s], bool errors = false) { expectResImpl(kj::mv(result), arrayPtr(expected, s), errors); } // Handy reference for surrogate pair edge cases: // // \ud800 -> \xed\xa0\x80 // \udc00 -> \xed\xb0\x80 // \udbff -> \xed\xaf\xbf // \udfff -> \xed\xbf\xbf KJ_TEST("encode UTF-8 to UTF-16") { expectRes(encodeUtf16(u8"foo"), u"foo"); expectRes(encodeUtf16(u8"ЗдравÑтвуйте"), u"ЗдравÑтвуйте"); expectRes(encodeUtf16(u8"中国网络"), u"中国网络"); expectRes(encodeUtf16(u8"😺â˜â˜„ðŸµ"), u"😺â˜â˜„ðŸµ"); } KJ_TEST("invalid UTF-8 to UTF-16") { // Disembodied continuation byte. expectRes(encodeUtf16("\x80"), u"\ufffd", true); expectRes(encodeUtf16("f\xbfo"), u"f\ufffdo", true); expectRes(encodeUtf16("f\xbf\x80\xb0o"), u"f\ufffdo", true); // Missing continuation bytes. expectRes(encodeUtf16("\xc2x"), u"\ufffdx", true); expectRes(encodeUtf16("\xe0x"), u"\ufffdx", true); expectRes(encodeUtf16("\xe0\xa0x"), u"\ufffdx", true); expectRes(encodeUtf16("\xf0x"), u"\ufffdx", true); expectRes(encodeUtf16("\xf0\x90x"), u"\ufffdx", true); expectRes(encodeUtf16("\xf0\x90\x80x"), u"\ufffdx", true); // Overlong sequences. expectRes(encodeUtf16("\xc0\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xc1\xbf"), u"\ufffd", true); expectRes(encodeUtf16("\xc2\x80"), u"\u0080", false); expectRes(encodeUtf16("\xdf\xbf"), u"\u07ff", false); expectRes(encodeUtf16("\xe0\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xe0\x9f\xbf"), u"\ufffd", true); expectRes(encodeUtf16("\xe0\xa0\x80"), u"\u0800", false); expectRes(encodeUtf16("\xef\xbf\xbe"), u"\ufffe", false); // Due to a classic off-by-one error, GCC 4.x rather hilariously encodes '\uffff' as the // "surrogate pair" 0xd7ff, 0xdfff: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41698 if (kj::size(u"\uffff") == 2) { expectRes(encodeUtf16("\xef\xbf\xbf"), u"\uffff", false); } expectRes(encodeUtf16("\xf0\x80\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xf0\x8f\xbf\xbf"), u"\ufffd", true); expectRes(encodeUtf16("\xf0\x90\x80\x80"), u"\U00010000", false); expectRes(encodeUtf16("\xf4\x8f\xbf\xbf"), u"\U0010ffff", false); // Out of Unicode range. expectRes(encodeUtf16("\xf5\x80\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xf8\xbf\x80\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xfc\xbf\x80\x80\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xfe\xbf\x80\x80\x80\x80\x80"), u"\ufffd", true); expectRes(encodeUtf16("\xff\xbf\x80\x80\x80\x80\x80\x80"), u"\ufffd", true); // Surrogates encoded as separate UTF-8 code points are flagged as errors but allowed to decode // to UTF-16 surrogate values. expectRes(encodeUtf16("\xed\xb0\x80\xed\xaf\xbf"), u"\xdc00\xdbff", true); expectRes(encodeUtf16("\xed\xbf\xbf\xed\xa0\x80"), u"\xdfff\xd800", true); expectRes(encodeUtf16("\xed\xb0\x80\xed\xbf\xbf"), u"\xdc00\xdfff", true); expectRes(encodeUtf16("f\xed\xa0\x80"), u"f\xd800", true); expectRes(encodeUtf16("f\xed\xa0\x80x"), u"f\xd800x", true); expectRes(encodeUtf16("f\xed\xa0\x80\xed\xa0\x80x"), u"f\xd800\xd800x", true); // However, if successive UTF-8 codepoints decode to a proper surrogate pair, the second // surrogate is replaced with the Unicode replacement character to avoid creating valid UTF-16. expectRes(encodeUtf16("\xed\xa0\x80\xed\xbf\xbf"), u"\xd800\xfffd", true); expectRes(encodeUtf16("\xed\xaf\xbf\xed\xb0\x80"), u"\xdbff\xfffd", true); } KJ_TEST("encode UTF-8 to UTF-32") { expectRes(encodeUtf32(u8"foo"), U"foo"); expectRes(encodeUtf32(u8"ЗдравÑтвуйте"), U"ЗдравÑтвуйте"); expectRes(encodeUtf32(u8"中国网络"), U"中国网络"); expectRes(encodeUtf32(u8"😺â˜â˜„ðŸµ"), U"😺â˜â˜„ðŸµ"); } KJ_TEST("invalid UTF-8 to UTF-32") { // Disembodied continuation byte. expectRes(encodeUtf32("\x80"), U"\ufffd", true); expectRes(encodeUtf32("f\xbfo"), U"f\ufffdo", true); expectRes(encodeUtf32("f\xbf\x80\xb0o"), U"f\ufffdo", true); // Missing continuation bytes. expectRes(encodeUtf32("\xc2x"), U"\ufffdx", true); expectRes(encodeUtf32("\xe0x"), U"\ufffdx", true); expectRes(encodeUtf32("\xe0\xa0x"), U"\ufffdx", true); expectRes(encodeUtf32("\xf0x"), U"\ufffdx", true); expectRes(encodeUtf32("\xf0\x90x"), U"\ufffdx", true); expectRes(encodeUtf32("\xf0\x90\x80x"), U"\ufffdx", true); // Overlong sequences. expectRes(encodeUtf32("\xc0\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xc1\xbf"), U"\ufffd", true); expectRes(encodeUtf32("\xc2\x80"), U"\u0080", false); expectRes(encodeUtf32("\xdf\xbf"), U"\u07ff", false); expectRes(encodeUtf32("\xe0\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xe0\x9f\xbf"), U"\ufffd", true); expectRes(encodeUtf32("\xe0\xa0\x80"), U"\u0800", false); expectRes(encodeUtf32("\xef\xbf\xbf"), U"\uffff", false); expectRes(encodeUtf32("\xf0\x80\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xf0\x8f\xbf\xbf"), U"\ufffd", true); expectRes(encodeUtf32("\xf0\x90\x80\x80"), U"\U00010000", false); expectRes(encodeUtf32("\xf4\x8f\xbf\xbf"), U"\U0010ffff", false); // Out of Unicode range. expectRes(encodeUtf32("\xf5\x80\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xf8\xbf\x80\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xfc\xbf\x80\x80\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xfe\xbf\x80\x80\x80\x80\x80"), U"\ufffd", true); expectRes(encodeUtf32("\xff\xbf\x80\x80\x80\x80\x80\x80"), U"\ufffd", true); } KJ_TEST("decode UTF-16 to UTF-8") { expectRes(decodeUtf16(u"foo"), u8"foo"); expectRes(decodeUtf16(u"ЗдравÑтвуйте"), u8"ЗдравÑтвуйте"); expectRes(decodeUtf16(u"中国网络"), u8"中国网络"); expectRes(decodeUtf16(u"😺â˜â˜„ðŸµ"), u8"😺â˜â˜„ðŸµ"); } KJ_TEST("invalid UTF-16 to UTF-8") { // Surrogates in wrong order. expectRes(decodeUtf16(u"\xdc00\xdbff"), "\xed\xb0\x80\xed\xaf\xbf", true); expectRes(decodeUtf16(u"\xdfff\xd800"), "\xed\xbf\xbf\xed\xa0\x80", true); // Missing second surrogate. expectRes(decodeUtf16(u"f\xd800"), "f\xed\xa0\x80", true); expectRes(decodeUtf16(u"f\xd800x"), "f\xed\xa0\x80x", true); expectRes(decodeUtf16(u"f\xd800\xd800x"), "f\xed\xa0\x80\xed\xa0\x80x", true); } KJ_TEST("decode UTF-32 to UTF-8") { expectRes(decodeUtf32(U"foo"), u8"foo"); expectRes(decodeUtf32(U"ЗдравÑтвуйте"), u8"ЗдравÑтвуйте"); expectRes(decodeUtf32(U"中国网络"), u8"中国网络"); expectRes(decodeUtf32(U"😺â˜â˜„ðŸµ"), u8"😺â˜â˜„ðŸµ"); } KJ_TEST("invalid UTF-32 to UTF-8") { // Surrogates rejected. expectRes(decodeUtf32(U"\xdfff\xd800"), "\xed\xbf\xbf\xed\xa0\x80", true); // Even if it would be a valid surrogate pair in UTF-16. expectRes(decodeUtf32(U"\xd800\xdfff"), "\xed\xa0\x80\xed\xbf\xbf", true); } KJ_TEST("round-trip invalid UTF-16") { const char16_t INVALID[] = u"\xdfff foo \xd800\xdc00 bar \xdc00\xd800 baz \xdbff qux \xd800"; expectRes(encodeUtf16(decodeUtf16(INVALID)), INVALID, true); expectRes(encodeUtf16(decodeUtf32(encodeUtf32(decodeUtf16(INVALID)))), INVALID, true); } KJ_TEST("EncodingResult as a Maybe") { KJ_IF_MAYBE(result, encodeUtf16("\x80")) { KJ_FAIL_EXPECT("expected failure"); } KJ_IF_MAYBE(result, encodeUtf16("foo")) { // good } else { KJ_FAIL_EXPECT("expected success"); } KJ_EXPECT(KJ_ASSERT_NONNULL(decodeUtf16(u"foo")) == "foo"); } KJ_TEST("encode to wchar_t") { expectRes(encodeWideString(u8"foo"), L"foo"); expectRes(encodeWideString(u8"ЗдравÑтвуйте"), L"ЗдравÑтвуйте"); expectRes(encodeWideString(u8"中国网络"), L"中国网络"); expectRes(encodeWideString(u8"😺â˜â˜„ðŸµ"), L"😺â˜â˜„ðŸµ"); } KJ_TEST("decode from wchar_t") { expectRes(decodeWideString(L"foo"), u8"foo"); expectRes(decodeWideString(L"ЗдравÑтвуйте"), u8"ЗдравÑтвуйте"); expectRes(decodeWideString(L"中国网络"), u8"中国网络"); expectRes(decodeWideString(L"😺â˜â˜„ðŸµ"), u8"😺â˜â˜„ðŸµ"); } // ======================================================================================= KJ_TEST("hex encoding/decoding") { byte bytes[] = {0x12, 0x34, 0xab, 0xf2}; KJ_EXPECT(encodeHex(bytes) == "1234abf2"); expectRes(decodeHex("1234abf2"), bytes); expectRes(decodeHex("1234abf21"), bytes, true); bytes[2] = 0xa0; expectRes(decodeHex("1234axf2"), bytes, true); bytes[2] = 0x0b; expectRes(decodeHex("1234xbf2"), bytes, true); } constexpr char RFC2396_FRAGMENT_SET_DIFF[] = "#$&+,/:;=?@[\\]^{|}"; // These are the characters reserved in RFC 2396, but not in the fragment percent encode set. KJ_TEST("URI encoding/decoding") { KJ_EXPECT(encodeUriComponent("foo") == "foo"); KJ_EXPECT(encodeUriComponent("foo bar") == "foo%20bar"); KJ_EXPECT(encodeUriComponent("\xab\xba") == "%AB%BA"); KJ_EXPECT(encodeUriComponent(StringPtr("foo\0bar", 7)) == "foo%00bar"); KJ_EXPECT(encodeUriComponent(RFC2396_FRAGMENT_SET_DIFF) == "%23%24%26%2B%2C%2F%3A%3B%3D%3F%40%5B%5C%5D%5E%7B%7C%7D"); // Encode characters reserved by application/x-www-form-urlencoded, but not by RFC 2396. KJ_EXPECT(encodeUriComponent("'foo'! (~)") == "'foo'!%20(~)"); expectRes(decodeUriComponent("foo%20bar"), "foo bar"); expectRes(decodeUriComponent("%ab%BA"), "\xab\xba"); expectRes(decodeUriComponent("foo%1xxx"), "foo\1xxx", true); expectRes(decodeUriComponent("foo%1"), "foo\1", true); expectRes(decodeUriComponent("foo%xxx"), "fooxxx", true); expectRes(decodeUriComponent("foo%"), "foo", true); { byte bytes[] = {12, 34, 56}; KJ_EXPECT(decodeBinaryUriComponent(encodeUriComponent(bytes)).asPtr() == bytes); // decodeBinaryUriComponent() takes a DecodeUriOptions struct as its second parameter, but it // once took a single `bool nulTerminate`. Verify that the old behavior still compiles and // works. auto bytesWithNul = decodeBinaryUriComponent(encodeUriComponent(bytes), true); KJ_ASSERT(bytesWithNul.size() == 4); KJ_EXPECT(bytesWithNul[3] == '\0'); KJ_EXPECT(bytesWithNul.slice(0, 3) == bytes); } } KJ_TEST("URL component encoding") { KJ_EXPECT(encodeUriFragment("foo") == "foo"); KJ_EXPECT(encodeUriFragment("foo bar") == "foo%20bar"); KJ_EXPECT(encodeUriFragment("\xab\xba") == "%AB%BA"); KJ_EXPECT(encodeUriFragment(StringPtr("foo\0bar", 7)) == "foo%00bar"); KJ_EXPECT(encodeUriFragment(RFC2396_FRAGMENT_SET_DIFF) == RFC2396_FRAGMENT_SET_DIFF); KJ_EXPECT(encodeUriPath("foo") == "foo"); KJ_EXPECT(encodeUriPath("foo bar") == "foo%20bar"); KJ_EXPECT(encodeUriPath("\xab\xba") == "%AB%BA"); KJ_EXPECT(encodeUriPath(StringPtr("foo\0bar", 7)) == "foo%00bar"); KJ_EXPECT(encodeUriPath(RFC2396_FRAGMENT_SET_DIFF) == "%23$&+,%2F:;=%3F@[%5C]^%7B|%7D"); KJ_EXPECT(encodeUriUserInfo("foo") == "foo"); KJ_EXPECT(encodeUriUserInfo("foo bar") == "foo%20bar"); KJ_EXPECT(encodeUriUserInfo("\xab\xba") == "%AB%BA"); KJ_EXPECT(encodeUriUserInfo(StringPtr("foo\0bar", 7)) == "foo%00bar"); KJ_EXPECT(encodeUriUserInfo(RFC2396_FRAGMENT_SET_DIFF) == "%23$&+,%2F%3A%3B%3D%3F%40%5B%5C%5D%5E%7B%7C%7D"); // NOTE: None of these functions have explicit decode equivalents. } KJ_TEST("application/x-www-form-urlencoded encoding/decoding") { KJ_EXPECT(encodeWwwForm("foo") == "foo"); KJ_EXPECT(encodeWwwForm("foo bar") == "foo+bar"); KJ_EXPECT(encodeWwwForm("\xab\xba") == "%AB%BA"); KJ_EXPECT(encodeWwwForm(StringPtr("foo\0bar", 7)) == "foo%00bar"); // Encode characters reserved by application/x-www-form-urlencoded, but not by RFC 2396. KJ_EXPECT(encodeWwwForm("'foo'! (~)") == "%27foo%27%21+%28%7E%29"); expectRes(decodeWwwForm("foo%20bar"), "foo bar"); expectRes(decodeWwwForm("foo+bar"), "foo bar"); expectRes(decodeWwwForm("%ab%BA"), "\xab\xba"); expectRes(decodeWwwForm("foo%1xxx"), "foo\1xxx", true); expectRes(decodeWwwForm("foo%1"), "foo\1", true); expectRes(decodeWwwForm("foo%xxx"), "fooxxx", true); expectRes(decodeWwwForm("foo%"), "foo", true); { byte bytes[] = {12, 34, 56}; DecodeUriOptions options { /*.nulTerminate=*/false, /*.plusToSpace=*/true }; KJ_EXPECT(decodeBinaryUriComponent(encodeWwwForm(bytes), options) == bytes); } } KJ_TEST("C escape encoding/decoding") { KJ_EXPECT(encodeCEscape("fooo\a\b\f\n\r\t\v\'\"\\barПривет, Мир! Ж=О") == "fooo\\a\\b\\f\\n\\r\\t\\v\\\'\\\"\\\\bar\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82\x2c\x20\xd0\x9c\xd0\xb8\xd1\x80\x21\x20\xd0\x96\x3d\xd0\x9e"); KJ_EXPECT(encodeCEscape("foo\x01\x7fxxx") == "foo\\001\\177xxx"); byte bytes[] = {'f', 'o', 'o', 0, '\x01', '\x7f', 'x', 'x', 'x', 128, 254, 255}; KJ_EXPECT(encodeCEscape(bytes) == "foo\\000\\001\\177xxx\\200\\376\\377"); expectRes(decodeCEscape("fooo\\a\\b\\f\\n\\r\\t\\v\\\'\\\"\\\\bar"), "fooo\a\b\f\n\r\t\v\'\"\\bar"); expectRes(decodeCEscape("foo\\x01\\x7fxxx"), "foo\x01\x7fxxx"); expectRes(decodeCEscape("foo\\001\\177234"), "foo\001\177234"); expectRes(decodeCEscape("foo\\x1"), "foo\x1"); expectRes(decodeCEscape("foo\\1"), "foo\1"); expectRes(decodeCEscape("foo\\u1234bar"), u8"foo\u1234bar"); expectRes(decodeCEscape("foo\\U00045678bar"), u8"foo\U00045678bar"); // Error cases. expectRes(decodeCEscape("foo\\"), "foo", true); expectRes(decodeCEscape("foo\\x123x"), u8"foo\x23x", true); expectRes(decodeCEscape("foo\\u12"), u8"foo\u0012", true); expectRes(decodeCEscape("foo\\u12xxx"), u8"foo\u0012xxx", true); expectRes(decodeCEscape("foo\\U12"), u8"foo\u0012", true); expectRes(decodeCEscape("foo\\U12xxxxxxxx"), u8"foo\u0012xxxxxxxx", true); } KJ_TEST("base64 encoding/decoding") { { auto encoded = encodeBase64(StringPtr("").asBytes(), false); KJ_EXPECT(encoded == "", encoded, encoded.size()); KJ_EXPECT(heapString(decodeBase64(encoded.asArray()).asChars()) == ""); } { auto encoded = encodeBase64(StringPtr("foo").asBytes(), false); KJ_EXPECT(encoded == "Zm9v", encoded, encoded.size()); auto decoded = decodeBase64(encoded.asArray()); KJ_EXPECT(!decoded.hadErrors); KJ_EXPECT(heapString(decoded.asChars()) == "foo"); } { auto encoded = encodeBase64(StringPtr("quux").asBytes(), false); KJ_EXPECT(encoded == "cXV1eA==", encoded, encoded.size()); KJ_EXPECT(heapString(decodeBase64(encoded.asArray()).asChars()) == "quux"); } { auto encoded = encodeBase64(StringPtr("corge").asBytes(), false); KJ_EXPECT(encoded == "Y29yZ2U=", encoded); auto decoded = decodeBase64(encoded.asArray()); KJ_EXPECT(!decoded.hadErrors); KJ_EXPECT(heapString(decoded.asChars()) == "corge"); } { auto decoded = decodeBase64("Y29yZ2U"); KJ_EXPECT(!decoded.hadErrors); KJ_EXPECT(heapString(decoded.asChars()) == "corge"); } { auto decoded = decodeBase64("Y\n29y Z@2U=\n"); KJ_EXPECT(decoded.hadErrors); // @-sign is invalid base64 input. KJ_EXPECT(heapString(decoded.asChars()) == "corge"); } { auto decoded = decodeBase64("Y\n29y Z2U=\n"); KJ_EXPECT(!decoded.hadErrors); KJ_EXPECT(heapString(decoded.asChars()) == "corge"); } // Too much padding. KJ_EXPECT(decodeBase64("Y29yZ2U==").hadErrors); KJ_EXPECT(decodeBase64("Y29yZ===").hadErrors); // Non-terminal padding. KJ_EXPECT(decodeBase64("ab=c").hadErrors); { auto encoded = encodeBase64(StringPtr("corge").asBytes(), true); KJ_EXPECT(encoded == "Y29yZ2U=\n", encoded); } StringPtr fullLine = "012345678901234567890123456789012345678901234567890123"; { auto encoded = encodeBase64(fullLine.asBytes(), false); KJ_EXPECT( encoded == "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz", encoded); } { auto encoded = encodeBase64(fullLine.asBytes(), true); KJ_EXPECT( encoded == "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz\n", encoded); } String multiLine = str(fullLine, "456"); { auto encoded = encodeBase64(multiLine.asBytes(), false); KJ_EXPECT( encoded == "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2", encoded); } { auto encoded = encodeBase64(multiLine.asBytes(), true); KJ_EXPECT( encoded == "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz\n" "NDU2\n", encoded); } } KJ_TEST("base64 url encoding") { { // Handles empty. auto encoded = encodeBase64Url(StringPtr("").asBytes()); KJ_EXPECT(encoded == "", encoded, encoded.size()); } { // Handles paddingless encoding. auto encoded = encodeBase64Url(StringPtr("foo").asBytes()); KJ_EXPECT(encoded == "Zm9v", encoded, encoded.size()); } { // Handles padded encoding. auto encoded1 = encodeBase64Url(StringPtr("quux").asBytes()); KJ_EXPECT(encoded1 == "cXV1eA", encoded1, encoded1.size()); auto encoded2 = encodeBase64Url(StringPtr("corge").asBytes()); KJ_EXPECT(encoded2 == "Y29yZ2U", encoded2, encoded2.size()); } { // No line breaks. StringPtr fullLine = "012345678901234567890123456789012345678901234567890123"; auto encoded = encodeBase64Url(StringPtr(fullLine).asBytes()); KJ_EXPECT( encoded == "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz", encoded); } { // Replaces plusses. const byte data[] = { 0b11111011, 0b11101111, 0b10111110 }; auto encoded = encodeBase64Url(data); KJ_EXPECT(encoded == "----", encoded, encoded.size(), data); } { // Replaces slashes. const byte data[] = { 0b11111111, 0b11111111, 0b11111111 }; auto encoded = encodeBase64Url(data); KJ_EXPECT(encoded == "____", encoded, encoded.size(), data); } } } // namespace } // namespace kj capnproto-c++-1.1.0/src/kj/exception.h0000644000175000017500000005162214712011043020303 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #pragma once #include "memory.h" #include "array.h" #include "string.h" #include "windows-sanity.h" // work-around macro conflict with `ERROR` KJ_BEGIN_HEADER namespace kj { class ExceptionImpl; template class Function; class Exception { // Exception thrown in case of fatal errors. // // Actually, a subclass of this which also implements std::exception will be thrown, but we hide // that fact from the interface to avoid #including . public: enum class Type { // What kind of failure? FAILED = 0, // Something went wrong. This is the usual error type. KJ_ASSERT and KJ_REQUIRE throw this // error type. OVERLOADED = 1, // The call failed because of a temporary lack of resources. This could be space resources // (out of memory, out of disk space) or time resources (request queue overflow, operation // timed out). // // The operation might work if tried again, but it should NOT be repeated immediately as this // may simply exacerbate the problem. DISCONNECTED = 2, // The call required communication over a connection that has been lost. The callee will need // to re-establish connections and try again. UNIMPLEMENTED = 3 // The requested method is not implemented. The caller may wish to revert to a fallback // approach based on other methods. // IF YOU ADD A NEW VALUE: // - Update the stringifier. // - Update Cap'n Proto's RPC protocol's Exception.Type enum. }; Exception(Type type, const char* file, int line, String description = nullptr) noexcept; Exception(Type type, String file, int line, String description = nullptr) noexcept; Exception(const Exception& other) noexcept; Exception(Exception&& other) = default; ~Exception() noexcept; const char* getFile() const { return file; } int getLine() const { return line; } Type getType() const { return type; } StringPtr getDescription() const { return description; } ArrayPtr getStackTrace() const { return arrayPtr(trace, traceCount); } void setDescription(kj::String&& desc) { description = kj::mv(desc); } StringPtr getRemoteTrace() const { return remoteTrace; } void setRemoteTrace(kj::String&& value) { remoteTrace = kj::mv(value); } // Additional stack trace data originating from a remote server. If present, then // `getStackTrace()` only traces up until entry into the RPC system, and the remote trace // contains any trace information returned over the wire. This string is human-readable but the // format is otherwise unspecified. struct Context { // Describes a bit about what was going on when the exception was thrown. const char* file; int line; String description; Maybe> next; Context(const char* file, int line, String&& description, Maybe>&& next) : file(file), line(line), description(mv(description)), next(mv(next)) {} Context(const Context& other) noexcept; }; inline Maybe getContext() const { KJ_IF_MAYBE(c, context) { return **c; } else { return nullptr; } } void wrapContext(const char* file, int line, String&& description); // Wraps the context in a new node. This becomes the head node returned by getContext() -- it // is expected that contexts will be added in reverse order as the exception passes up the // callback stack. KJ_NOINLINE void extendTrace(uint ignoreCount, uint limit = kj::maxValue); // Append the current stack trace to the exception's trace, ignoring the first `ignoreCount` // frames (see `getStackTrace()` for discussion of `ignoreCount`). // // If `limit` is set, limit the number of frames added to the given number. KJ_NOINLINE void truncateCommonTrace(); // Remove the part of the stack trace which the exception shares with the caller of this method. // This is used by the async library to remove the async infrastructure from the stack trace // before replacing it with the async trace. void addTrace(void* ptr); // Append the given pointer to the backtrace, if it is not already full. This is used by the // async library to trace through the promise chain that led to the exception. KJ_NOINLINE void addTraceHere(); // Adds the location that called this method to the stack trace. private: String ownFile; const char* file; int line; Type type; String description; Maybe> context; String remoteTrace; void* trace[32]; uint traceCount; bool isFullTrace = false; // Is `trace` a full trace to the top of the stack (or as close as we could get before we ran // out of space)? If this is false, then `trace` is instead a partial trace covering just the // frames between where the exception was thrown and where it was caught. // // extendTrace() transitions this to true, and truncateCommonTrace() changes it back to false. // // In theory, an exception should only hold a full trace when it is in the process of being // thrown via the C++ exception handling mechanism -- extendTrace() is called before the throw // and truncateCommonTrace() after it is caught. Note that when exceptions propagate through // async promises, the trace is extended one frame at a time instead, so isFullTrace should // remain false. friend class ExceptionImpl; }; struct CanceledException { }; // This exception is thrown to force-unwind a stack in order to immediately cancel whatever that // stack was doing. It is used in the implementation of fibers in particular. Application code // should almost never catch this exception, unless you need to modify stack unwinding for some // reason. kj::runCatchingExceptions() does not catch it. StringPtr KJ_STRINGIFY(Exception::Type type); String KJ_STRINGIFY(const Exception& e); // ======================================================================================= enum class LogSeverity { INFO, // Information describing what the code is up to, which users may request to see // with a flag like `--verbose`. Does not indicate a problem. Not printed by // default; you must call setLogLevel(INFO) to enable. WARNING, // A problem was detected but execution can continue with correct output. ERROR, // Something is wrong, but execution can continue with garbage output. FATAL, // Something went wrong, and execution cannot continue. DBG // Temporary debug logging. See KJ_DBG. // Make sure to update the stringifier if you add a new severity level. }; StringPtr KJ_STRINGIFY(LogSeverity severity); class ExceptionCallback { // If you don't like C++ exceptions, you may implement and register an ExceptionCallback in order // to perform your own exception handling. For example, a reasonable thing to do is to have // onRecoverableException() set a flag indicating that an error occurred, and then check for that // flag just before writing to storage and/or returning results to the user. If the flag is set, // discard whatever you have and return an error instead. // // ExceptionCallbacks must always be allocated on the stack. When an exception is thrown, the // newest ExceptionCallback on the calling thread's stack is called. The default implementation // of each method calls the next-oldest ExceptionCallback for that thread. Thus the callbacks // behave a lot like try/catch blocks, except that they are called before any stack unwinding // occurs. public: ExceptionCallback(); KJ_DISALLOW_COPY_AND_MOVE(ExceptionCallback); virtual ~ExceptionCallback() noexcept(false); virtual void onRecoverableException(Exception&& exception); // Called when an exception has been raised, but the calling code has the ability to continue by // producing garbage output. This method _should_ throw the exception, but is allowed to simply // return if garbage output is acceptable. // // The global default implementation throws an exception unless the library was compiled with // -fno-exceptions, in which case it logs an error and returns. virtual void onFatalException(Exception&& exception); // Called when an exception has been raised and the calling code cannot continue. If this method // returns normally, abort() will be called. The method must throw the exception to avoid // aborting. // // The global default implementation throws an exception unless the library was compiled with // -fno-exceptions, in which case it logs an error and returns. virtual void logMessage(LogSeverity severity, const char* file, int line, int contextDepth, String&& text); // Called when something wants to log some debug text. `contextDepth` indicates how many levels // of context the message passed through; it may make sense to indent the message accordingly. // // The global default implementation writes the text to stderr. enum class StackTraceMode { FULL, // Stringifying a stack trace will attempt to determine source file and line numbers. This may // be expensive. For example, on Linux, this shells out to `addr2line`. // // This is the default in debug builds. ADDRESS_ONLY, // Stringifying a stack trace will only generate a list of code addresses. // // This is the default in release builds. NONE // Generating a stack trace will always return an empty array. // // This avoids ever unwinding the stack. On Windows in particular, the stack unwinding library // has been observed to be pretty slow, so exception-heavy code might benefit significantly // from this setting. (But exceptions should be rare...) }; virtual StackTraceMode stackTraceMode(); // Returns the current preferred stack trace mode. virtual Function)> getThreadInitializer(); // Called just before a new thread is spawned using kj::Thread. Returns a function which should // be invoked inside the new thread to initialize the thread's ExceptionCallback. The initializer // function itself receives, as its parameter, the thread's main function, which it must call. protected: ExceptionCallback& next; private: ExceptionCallback(ExceptionCallback& next); class RootExceptionCallback; friend ExceptionCallback& getExceptionCallback(); friend class Thread; }; ExceptionCallback& getExceptionCallback(); // Returns the current exception callback. KJ_NOINLINE KJ_NORETURN(void throwFatalException(kj::Exception&& exception, uint ignoreCount = 0)); // Invoke the exception callback to throw the given fatal exception. If the exception callback // returns, abort. KJ_NOINLINE void throwRecoverableException(kj::Exception&& exception, uint ignoreCount = 0); // Invoke the exception callback to throw the given recoverable exception. If the exception // callback returns, return normally. // ======================================================================================= namespace _ { class Runnable; } template Maybe runCatchingExceptions(Func&& func); // Executes the given function (usually, a lambda returning nothing) catching any exceptions that // are thrown. Returns the Exception if there was one, or null if the operation completed normally. // Non-KJ exceptions will be wrapped. // // If exception are disabled (e.g. with -fno-exceptions), this will still detect whether any // recoverable exceptions occurred while running the function and will return those. #if !KJ_NO_EXCEPTIONS kj::Exception getCaughtExceptionAsKj(); // Call from the catch block of a try/catch to get a `kj::Exception` representing the exception // that was caught, the same way that `kj::runCatchingExceptions` would when catching an exception. // This is sometimes useful if `runCatchingExceptions()` doesn't quite fit your use case. You can // call this from any catch block, including `catch (...)`. // // Some exception types will actually be rethrown by this function, rather than returned. The most // common example is `CanceledException`, whose purpose is to unwind the stack and is not meant to // be caught. #endif // !KJ_NO_EXCEPTIONS class UnwindDetector { // Utility for detecting when a destructor is called due to unwind. Useful for: // - Avoiding throwing exceptions in this case, which would terminate the program. // - Detecting whether to commit or roll back a transaction. // // To use this class, either inherit privately from it or declare it as a member. The detector // works by comparing the exception state against that when the constructor was called, so for // an object that was actually constructed during exception unwind, it will behave as if no // unwind is taking place. This is usually the desired behavior. public: UnwindDetector(); bool isUnwinding() const; // Returns true if the current thread is in a stack unwind that it wasn't in at the time the // object was constructed. template void catchExceptionsIfUnwinding(Func&& func) const; // Runs the given function (e.g., a lambda). If isUnwinding() is true, any exceptions are // caught and treated as secondary faults, meaning they are considered to be side-effects of the // exception that is unwinding the stack. Otherwise, exceptions are passed through normally. private: uint uncaughtCount; #if !KJ_NO_EXCEPTIONS void catchThrownExceptionAsSecondaryFault() const; #endif }; #if KJ_NO_EXCEPTIONS namespace _ { // private class Runnable { public: virtual void run() = 0; }; template class RunnableImpl: public Runnable { public: RunnableImpl(Func&& func): func(kj::fwd(func)) {} void run() override { func(); } private: Func func; }; Maybe runCatchingExceptions(Runnable& runnable); } // namespace _ (private) #endif // KJ_NO_EXCEPTIONS template Maybe runCatchingExceptions(Func&& func) { #if KJ_NO_EXCEPTIONS _::RunnableImpl runnable(kj::fwd(func)); return _::runCatchingExceptions(runnable); #else try { func(); return nullptr; } catch (...) { return getCaughtExceptionAsKj(); } #endif } template void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const { #if KJ_NO_EXCEPTIONS // Can't possibly be unwinding... func(); #else if (isUnwinding()) { try { func(); } catch (...) { catchThrownExceptionAsSecondaryFault(); } } else { func(); } #endif } #define KJ_ON_SCOPE_SUCCESS(code) \ ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \ KJ_DEFER(if (!KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; }) // Runs `code` if the current scope is exited normally (not due to an exception). #define KJ_ON_SCOPE_FAILURE(code) \ ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \ KJ_DEFER(if (KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; }) // Runs `code` if the current scope is exited due to an exception. // ======================================================================================= KJ_NOINLINE ArrayPtr getStackTrace(ArrayPtr space, uint ignoreCount); // Attempt to get the current stack trace, returning a list of pointers to instructions. The // returned array is a slice of `space`. Provide a larger `space` to get a deeper stack trace. // If the platform doesn't support stack traces, returns an empty array. // // `ignoreCount` items will be truncated from the front of the trace. This is useful for chopping // off a prefix of the trace that is uninteresting to the developer because it's just locations // inside the debug infrastructure that is requesting the trace. Be careful to mark functions as // KJ_NOINLINE if you intend to count them in `ignoreCount`. Note that, unfortunately, the // ignored entries will still waste space in the `space` array (and the returned array's `begin()` // is never exactly equal to `space.begin()` due to this effect, even if `ignoreCount` is zero // since `getStackTrace()` needs to ignore its own internal frames). String stringifyStackTrace(ArrayPtr); // Convert the stack trace to a string with file names and line numbers. This may involve executing // suprocesses. String stringifyStackTraceAddresses(ArrayPtr trace); StringPtr stringifyStackTraceAddresses(ArrayPtr trace, ArrayPtr scratch); // Construct a string containing just enough information about a stack trace to be able to convert // it to file and line numbers later using offline tools. This produces a sequence of // space-separated code location identifiers. Each identifier may be an absolute address // (hex number starting with 0x) or may be a module-relative address "@0x". The // latter case is preferred when ASLR is in effect and has loaded different modules at different // addresses. String getStackTrace(); // Get a stack trace right now and stringify it. Useful for debugging. void printStackTraceOnCrash(); // Registers signal handlers on common "crash" signals like SIGSEGV that will (attempt to) print // a stack trace. You should call this as early as possible on program startup. Programs using // KJ_MAIN get this automatically. void resetCrashHandlers(); // Resets all signal handlers set by printStackTraceOnCrash(). kj::StringPtr trimSourceFilename(kj::StringPtr filename); // Given a source code file name, trim off noisy prefixes like "src/" or // "/ekam-provider/canonical/". kj::String getCaughtExceptionType(); // Utility function which attempts to return the human-readable type name of the exception // currently being thrown. This can be called inside a catch block, including a catch (...) block, // for the purpose of error logging. This function is best-effort; on some platforms it may simply // return "(unknown)". #if !KJ_NO_EXCEPTIONS class InFlightExceptionIterator { // A class that can be used to iterate over exceptions that are in-flight in the current thread, // meaning they are either uncaught, or caught by a catch block that is current executing. // // This is meant for debugging purposes, and the results are best-effort. The C++ standard // library does not provide any way to inspect uncaught exceptions, so this class can only // discover KJ exceptions thrown using throwFatalException() or throwRecoverableException(). // All KJ code uses those two functions to throw exceptions, but if your own code uses a bare // `throw`, or if the standard library throws an exception, these cannot be inspected. // // This class is safe to use in a signal handler. public: InFlightExceptionIterator(); Maybe next(); private: const Exception* ptr; }; #endif // !KJ_NO_EXCEPTIONS kj::Exception getDestructionReason(void* traceSeparator, kj::Exception::Type defaultType, const char* defaultFile, int defaultLine, kj::StringPtr defaultDescription); // Returns an exception that attempts to capture why a destructor has been invoked. If a KJ // exception is currently in-flight (see InFlightExceptionIterator), then that exception is // returned. Otherwise, an exception is constructed using the current stack trace and the type, // file, line, and description provided. In the latter case, `traceSeparator` is appended to the // stack trace; this should be a pointer to some dummy symbol which acts as a separator between the // original stack trace and any new trace frames added later. kj::ArrayPtr computeRelativeTrace( kj::ArrayPtr trace, kj::ArrayPtr relativeTo); // Given two traces expected to have started from the same root, try to find the part of `trace` // that is different from `relativeTo`, considering that either or both traces might be truncated. // // This is useful for debugging, when reporting several related traces at once. void requireOnStack(void* ptr, kj::StringPtr description); // Throw an exception if `ptr` does not appear to point to something near the top of the stack. // Used as a safety check for types that must be stack-allocated, like ExceptionCallback. } // namespace kj KJ_END_HEADER capnproto-c++-1.1.0/src/kj/main.c++0000644000175000017500000006262014712011043017352 0ustar00kentonkenton00000000000000// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors // Licensed under the MIT License: // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #if _WIN32 #include "win32-api-version.h" #endif #include "main.h" #include "debug.h" #include "arena.h" #include "miniposix.h" #include #include #include #include #include #if _WIN32 #include #include "windows-sanity.h" #else #include #endif namespace kj { // ======================================================================================= TopLevelProcessContext::TopLevelProcessContext(StringPtr programName) : programName(programName), cleanShutdown(getenv("KJ_CLEAN_SHUTDOWN") != nullptr) { printStackTraceOnCrash(); } StringPtr TopLevelProcessContext::getProgramName() { return programName; } void TopLevelProcessContext::exit() { int exitCode = hadErrors ? 1 : 0; if (cleanShutdown) { #if KJ_NO_EXCEPTIONS // This is the best we can do. warning("warning: KJ_CLEAN_SHUTDOWN may not work correctly when compiled " "with -fno-exceptions."); ::exit(exitCode); #else throw CleanShutdownException { exitCode }; #endif } _exit(exitCode); } #if _WIN32 void setStandardIoMode(int fd) { // Set mode to binary if the fd is not a console. HANDLE handle = reinterpret_cast(_get_osfhandle(fd)); DWORD consoleMode; if (GetConsoleMode(handle, &consoleMode)) { // It's a console. } else { KJ_SYSCALL(_setmode(fd, _O_BINARY)); } } #else void setStandardIoMode(int fd) {} #endif static void writeLineToFd(int fd, StringPtr message) { // Write the given message to the given file descriptor with a trailing newline iff the message // is non-empty and doesn't already have a trailing newline. We use writev() to do this in a // single system call without any copying (OS permitting). if (message.size() == 0) { return; } #if _WIN32 KJ_STACK_ARRAY(char, newlineExpansionBuffer, 2 * (message.size() + 1), 128, 512); char* p = newlineExpansionBuffer.begin(); for(char ch : message) { if(ch == '\n') { *(p++) = '\r'; } *(p++) = ch; } if(!message.endsWith("\n")) { *(p++) = '\r'; *(p++) = '\n'; } size_t newlineExpandedSize = p - newlineExpansionBuffer.begin(); KJ_ASSERT(newlineExpandedSize <= newlineExpansionBuffer.size()); HANDLE handle = reinterpret_cast(_get_osfhandle(fd)); DWORD consoleMode; bool redirectedToFile = !GetConsoleMode(handle, &consoleMode); DWORD writtenSize; if(redirectedToFile) { WriteFile(handle, newlineExpansionBuffer.begin(), newlineExpandedSize, &writtenSize, nullptr); } else { KJ_STACK_ARRAY(wchar_t, buffer, newlineExpandedSize, 128, 512); size_t finalSize = MultiByteToWideChar( CP_UTF8, 0, newlineExpansionBuffer.begin(), newlineExpandedSize, buffer.begin(), buffer.size()); KJ_ASSERT(finalSize <= buffer.size()); WriteConsoleW(handle, buffer.begin(), finalSize, &writtenSize, nullptr); } #else // Unfortunately the writev interface requires non-const pointers even though it won't modify // the data. struct iovec vec[2]; vec[0].iov_base = const_cast(message.begin()); vec[0].iov_len = message.size(); vec[1].iov_base = const_cast("\n"); vec[1].iov_len = 1; struct iovec* pos = vec; // Only use the second item in the vec if the message doesn't already end with \n. uint count = message.endsWith("\n") ? 1 : 2; for (;;) { ssize_t n = writev(fd, pos, count); if (n < 0) { if (errno == EINTR) { continue; } else { // This function is meant for writing to stdout and stderr. If writes fail on those FDs // there's not a whole lot we can reasonably do, so just ignore it. return; } } // Update chunks to discard what was successfully written. for (;;) { if (count == 0) { // Done writing. return; } else if (pos->iov_len <= implicitCast(n)) { // Wrote this entire chunk. n -= pos->iov_len; ++pos; --count; } else { // Wrote only part of this chunk. Adjust the pointer and then retry. pos->iov_base = reinterpret_cast(pos->iov_base) + n; pos->iov_len -= n; break; } } } #endif } void TopLevelProcessContext::warning(StringPtr message) { writeLineToFd(STDERR_FILENO, message); } void TopLevelProcessContext::error(StringPtr message) { hadErrors = true; writeLineToFd(STDERR_FILENO, message); } void TopLevelProcessContext::exitError(StringPtr message) { error(message); exit(); } void TopLevelProcessContext::exitInfo(StringPtr message) { writeLineToFd(STDOUT_FILENO, message); exit(); } void TopLevelProcessContext::increaseLoggingVerbosity() { // At the moment, there is only one log level that isn't enabled by default. _::Debug::setLogLevel(_::Debug::Severity::INFO); } // ======================================================================================= int runMainAndExit(ProcessContext& context, MainFunc&& func, int argc, char* argv[]) { setStandardIoMode(STDIN_FILENO); setStandardIoMode(STDOUT_FILENO); setStandardIoMode(STDERR_FILENO); #if !KJ_NO_EXCEPTIONS try { #endif KJ_ASSERT(argc > 0); KJ_STACK_ARRAY(StringPtr, params, argc - 1, 8, 32); for (int i = 1; i < argc; i++) { params[i - 1] = argv[i]; } KJ_IF_MAYBE(exception, runCatchingExceptions([&]() { func(argv[0], params); })) { context.error(str("*** Uncaught exception ***\n", *exception)); } context.exit(); #if !KJ_NO_EXCEPTIONS } catch (const TopLevelProcessContext::CleanShutdownException& e) { return e.exitCode; } #endif KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT } // ======================================================================================= struct MainBuilder::Impl { inline Impl(ProcessContext& context, StringPtr version, StringPtr briefDescription, StringPtr extendedDescription) : context(context), version(version), briefDescription(briefDescription), extendedDescription(extendedDescription) {} ProcessContext& context; StringPtr version; StringPtr briefDescription; StringPtr extendedDescription; Arena arena; struct CharArrayCompare { inline bool operator()(const ArrayPtr& a, const ArrayPtr& b) const { int cmp = memcmp(a.begin(), b.begin(), min(a.size(), b.size())); if (cmp == 0) { return a.size() < b.size(); } else { return cmp < 0; } } }; struct Option { ArrayPtr names; bool hasArg; union { Function* func; Function* funcWithArg; }; StringPtr argTitle; StringPtr helpText; }; class OptionDisplayOrder; std::map shortOptions; std::map, Option*, CharArrayCompare> longOptions; struct SubCommand { Function func; StringPtr helpText; }; std::map subCommands; struct Arg { StringPtr title; Function callback; uint minCount; uint maxCount; }; Vector args; Maybe> finalCallback; Option& addOption(std::initializer_list names, bool hasArg, StringPtr helpText) { KJ_REQUIRE(names.size() > 0, "option must have at least one name"); Option& option = arena.allocate